Merge pull request 're-worked GPIO implementation' (#3) from rework-gpio-impl into main
Reviewed-on: #3
This commit is contained in:
commit
ad6c5b26a2
@ -14,7 +14,7 @@ use zynq7000_hal::{
|
||||
BootMode,
|
||||
clocks::Clocks,
|
||||
gic::{GicConfigurator, GicInterruptHelper, Interrupt},
|
||||
gpio::{Mio7, MioPin, MioPins, Output, PinState},
|
||||
gpio::{Output, PinState, mio},
|
||||
gtc::Gtc,
|
||||
time::Hertz,
|
||||
uart::{ClkConfigRaw, TxAsync, Uart, UartConfig, on_interrupt_tx},
|
||||
@ -52,18 +52,16 @@ async fn main(spawner: Spawner) -> ! {
|
||||
let gtc = Gtc::new(dp.gtc, clocks.arm_clocks());
|
||||
zynq7000_embassy::init(clocks.arm_clocks(), gtc);
|
||||
|
||||
let mio_pins = MioPins::new(dp.gpio);
|
||||
let mio_pins = mio::Pins::new(dp.gpio);
|
||||
|
||||
// Set up the UART, we are logging with it.
|
||||
let uart_clk_config = ClkConfigRaw::new_autocalc_with_error(clocks.io_clocks(), 115200)
|
||||
.unwrap()
|
||||
.0;
|
||||
let uart_tx = mio_pins.mio48.into_uart();
|
||||
let uart_rx = mio_pins.mio49.into_uart();
|
||||
let mut uart = Uart::new_with_mio(
|
||||
dp.uart_1,
|
||||
UartConfig::new_with_clk_config(uart_clk_config),
|
||||
(uart_tx, uart_rx),
|
||||
(mio_pins.mio48, mio_pins.mio49),
|
||||
)
|
||||
.unwrap();
|
||||
uart.write_all(b"-- Zynq 7000 Logging example --\n\r")
|
||||
@ -77,7 +75,7 @@ async fn main(spawner: Spawner) -> ! {
|
||||
let boot_mode = BootMode::new();
|
||||
info!("Boot mode: {:?}", boot_mode);
|
||||
|
||||
let led = mio_pins.mio7.into_output(PinState::Low);
|
||||
let led = Output::new_for_mio(mio_pins.mio7, PinState::Low);
|
||||
spawner.spawn(led_task(led)).unwrap();
|
||||
let mut log_buf: [u8; 2048] = [0; 2048];
|
||||
let frame_queue = zynq7000_hal::log::rb::get_frame_queue();
|
||||
@ -89,7 +87,7 @@ async fn main(spawner: Spawner) -> ! {
|
||||
}
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn led_task(mut mio_led: MioPin<Mio7, Output>) {
|
||||
async fn led_task(mut mio_led: Output) {
|
||||
let mut ticker = Ticker::every(Duration::from_millis(1000));
|
||||
loop {
|
||||
mio_led.toggle().unwrap();
|
||||
|
@ -19,7 +19,7 @@ use zynq7000_hal::{
|
||||
BootMode,
|
||||
clocks::Clocks,
|
||||
gic::{GicConfigurator, GicInterruptHelper, Interrupt},
|
||||
gpio::{MioPins, PinState},
|
||||
gpio::{Output, PinState, mio},
|
||||
gtc::Gtc,
|
||||
time::Hertz,
|
||||
uart::{ClkConfigRaw, Uart, UartConfig},
|
||||
@ -54,7 +54,7 @@ async fn main(_spawner: Spawner) -> ! {
|
||||
unsafe {
|
||||
gic.enable_interrupts();
|
||||
}
|
||||
let mio_pins = MioPins::new(dp.gpio);
|
||||
let mio_pins = mio::Pins::new(dp.gpio);
|
||||
|
||||
// Set up global timer counter and embassy time driver.
|
||||
let gtc = Gtc::new(dp.gtc, clocks.arm_clocks());
|
||||
@ -71,12 +71,10 @@ async fn main(_spawner: Spawner) -> ! {
|
||||
let uart_clk_config = ClkConfigRaw::new_autocalc_with_error(clocks.io_clocks(), 115200)
|
||||
.unwrap()
|
||||
.0;
|
||||
let uart_tx = mio_pins.mio48.into_uart();
|
||||
let uart_rx = mio_pins.mio49.into_uart();
|
||||
let mut uart = Uart::new_with_mio(
|
||||
dp.uart_1,
|
||||
UartConfig::new_with_clk_config(uart_clk_config),
|
||||
(uart_tx, uart_rx),
|
||||
(mio_pins.mio48, mio_pins.mio49),
|
||||
)
|
||||
.unwrap();
|
||||
uart.write_all(b"-- Zynq 7000 Embassy Hello World --\n\r")
|
||||
@ -94,7 +92,7 @@ async fn main(_spawner: Spawner) -> ! {
|
||||
info!("Boot mode: {:?}", boot_mode);
|
||||
|
||||
let mut ticker = Ticker::every(Duration::from_millis(1000));
|
||||
let mut led = mio_pins.mio7.into_output(PinState::Low);
|
||||
let mut led = Output::new_for_mio(mio_pins.mio7, PinState::Low);
|
||||
let mut current_duty = 0;
|
||||
loop {
|
||||
led.toggle().unwrap();
|
||||
|
@ -12,7 +12,7 @@ use zynq7000_hal::{
|
||||
BootMode,
|
||||
clocks::Clocks,
|
||||
gic::{GicConfigurator, GicInterruptHelper, Interrupt},
|
||||
gpio::{MioPins, PinState},
|
||||
gpio::{Output, PinState, mio},
|
||||
gtc::Gtc,
|
||||
time::Hertz,
|
||||
uart::{ClkConfigRaw, Uart, UartConfig},
|
||||
@ -48,7 +48,7 @@ async fn main(_spawner: Spawner) -> ! {
|
||||
unsafe {
|
||||
gic.enable_interrupts();
|
||||
}
|
||||
let mio_pins = MioPins::new(dp.gpio);
|
||||
let mio_pins = mio::Pins::new(dp.gpio);
|
||||
|
||||
// Set up global timer counter and embassy time driver.
|
||||
let gtc = Gtc::new(dp.gtc, clocks.arm_clocks());
|
||||
@ -58,12 +58,10 @@ async fn main(_spawner: Spawner) -> ! {
|
||||
let uart_clk_config = ClkConfigRaw::new_autocalc_with_error(clocks.io_clocks(), 115200)
|
||||
.unwrap()
|
||||
.0;
|
||||
let uart_tx = mio_pins.mio48.into_uart();
|
||||
let uart_rx = mio_pins.mio49.into_uart();
|
||||
let mut uart = Uart::new_with_mio(
|
||||
dp.uart_1,
|
||||
UartConfig::new_with_clk_config(uart_clk_config),
|
||||
(uart_tx, uart_rx),
|
||||
(mio_pins.mio48, mio_pins.mio49),
|
||||
)
|
||||
.unwrap();
|
||||
uart.write_all(b"-- Zynq 7000 Embassy Hello World --\n\r")
|
||||
@ -81,7 +79,7 @@ async fn main(_spawner: Spawner) -> ! {
|
||||
info!("Boot mode: {:?}", boot_mode);
|
||||
|
||||
let mut ticker = Ticker::every(Duration::from_millis(1000));
|
||||
let mut led = mio_pins.mio7.into_output(PinState::Low);
|
||||
let mut led = Output::new_for_mio(mio_pins.mio7, PinState::Low);
|
||||
loop {
|
||||
info!("Hello, world!");
|
||||
led.toggle().unwrap();
|
||||
|
@ -10,7 +10,7 @@ use log::{error, info};
|
||||
use zynq7000_hal::{
|
||||
clocks::Clocks,
|
||||
gic::{GicConfigurator, GicInterruptHelper, Interrupt},
|
||||
gpio::{MioPins, PinState},
|
||||
gpio::{Output, PinState, mio},
|
||||
gtc::Gtc,
|
||||
prelude::*,
|
||||
time::Hertz,
|
||||
@ -58,13 +58,11 @@ pub fn main() -> ! {
|
||||
gtc.enable();
|
||||
|
||||
// This structure holds all MIO pins.
|
||||
let mio_pins = MioPins::new(dp.gpio);
|
||||
let uart_tx = mio_pins.mio48.into_uart();
|
||||
let uart_rx = mio_pins.mio49.into_uart();
|
||||
let mio_pins = mio::Pins::new(dp.gpio);
|
||||
let mut uart = Uart::new_with_mio(
|
||||
dp.uart_1,
|
||||
UartConfig::new_with_clk_config(uart_clk_config),
|
||||
(uart_tx, uart_rx),
|
||||
(mio_pins.mio48, mio_pins.mio49),
|
||||
)
|
||||
.unwrap();
|
||||
uart.write_all(b"-- Zynq 7000 GTC Ticks example --\n\r")
|
||||
@ -78,7 +76,7 @@ pub fn main() -> ! {
|
||||
)
|
||||
};
|
||||
|
||||
let mut led = mio_pins.mio7.into_output(PinState::Low);
|
||||
let mut led = Output::new_for_mio(mio_pins.mio7, PinState::Low);
|
||||
loop {
|
||||
info!(
|
||||
"MS_TICKS: {}",
|
||||
|
@ -11,7 +11,7 @@ use zynq7000_hal::{
|
||||
BootMode,
|
||||
clocks::Clocks,
|
||||
gic::{GicConfigurator, GicInterruptHelper, Interrupt},
|
||||
gpio::{MioPins, PinState},
|
||||
gpio::{Output, PinState, mio},
|
||||
gtc::Gtc,
|
||||
prelude::*,
|
||||
time::Hertz,
|
||||
@ -57,14 +57,12 @@ pub fn main() -> ! {
|
||||
gtc.enable_auto_increment();
|
||||
gtc.enable_interrupt();
|
||||
gtc.enable();
|
||||
let mio_pins = MioPins::new(dp.gpio);
|
||||
let uart_tx = mio_pins.mio48.into_uart();
|
||||
let uart_rx = mio_pins.mio49.into_uart();
|
||||
let mio_pins = mio::Pins::new(dp.gpio);
|
||||
|
||||
let mut uart = Uart::new_with_mio(
|
||||
dp.uart_1,
|
||||
UartConfig::new_with_clk_config(uart_clk_config),
|
||||
(uart_tx, uart_rx),
|
||||
(mio_pins.mio48, mio_pins.mio49),
|
||||
)
|
||||
.unwrap();
|
||||
uart.write_all(b"-- Zynq 7000 Logging example --\n\r")
|
||||
@ -81,7 +79,7 @@ pub fn main() -> ! {
|
||||
let boot_mode = BootMode::new();
|
||||
info!("Boot mode: {:?}", boot_mode);
|
||||
|
||||
let mut led = mio_pins.mio7.into_output(PinState::Low);
|
||||
let mut led = Output::new_for_mio(mio_pins.mio7, PinState::Low);
|
||||
loop {
|
||||
let gtc = gtc.read_timer();
|
||||
info!("Hello, world!");
|
||||
|
@ -6,7 +6,7 @@ use core::panic::PanicInfo;
|
||||
use cortex_ar::asm::nop;
|
||||
use embedded_hal::digital::StatefulOutputPin;
|
||||
use zynq7000::PsPeripherals;
|
||||
use zynq7000_hal::gpio::{MioPins, PinState};
|
||||
use zynq7000_hal::gpio::{Output, PinState, mio};
|
||||
use zynq7000_rt as _;
|
||||
|
||||
/// One user LED is MIO7
|
||||
@ -45,8 +45,8 @@ pub fn main() -> ! {
|
||||
}
|
||||
Lib::Hal => {
|
||||
let dp = PsPeripherals::take().unwrap();
|
||||
let mio_pins = MioPins::new(dp.gpio);
|
||||
let mut led = mio_pins.mio7.into_output(PinState::High);
|
||||
let mio_pins = mio::Pins::new(dp.gpio);
|
||||
let mut led = Output::new_for_mio(mio_pins.mio7, PinState::High);
|
||||
loop {
|
||||
led.toggle().unwrap();
|
||||
for _ in 0..5_000_000 {
|
||||
|
@ -11,7 +11,7 @@ keywords = ["no-std", "arm", "cortex-a", "amd", "zynq7000"]
|
||||
categories = ["embedded", "no-std", "hardware-support"]
|
||||
|
||||
[dependencies]
|
||||
cortex-ar = { git = "https://github.com/us-irs/cortex-ar.git", branch = "cortex-a-addition", features = ["critical-section-single-core"] }
|
||||
cortex-ar = { git = "https://github.com/rust-embedded/cortex-ar", branch = "main", features = ["critical-section-single-core"] }
|
||||
zynq7000-rt = { path = "../../zynq7000-rt" }
|
||||
zynq7000 = { path = "../../zynq7000" }
|
||||
zynq7000-hal = { path = "../../zynq7000-hal" }
|
||||
|
@ -22,7 +22,7 @@ use zynq7000_hal::{
|
||||
clocks::Clocks,
|
||||
configure_level_shifter,
|
||||
gic::{GicConfigurator, GicInterruptHelper, Interrupt},
|
||||
gpio::{EmioPin, GpioPins, PinState},
|
||||
gpio::{GpioPins, Output, PinState},
|
||||
gtc::Gtc,
|
||||
i2c,
|
||||
time::Hertz,
|
||||
@ -73,12 +73,10 @@ async fn main(_spawner: Spawner) -> ! {
|
||||
let uart_clk_config = uart::ClkConfigRaw::new_autocalc_with_error(clocks.io_clocks(), 115200)
|
||||
.unwrap()
|
||||
.0;
|
||||
let uart_tx = gpio_pins.mio.mio48.into_uart();
|
||||
let uart_rx = gpio_pins.mio.mio49.into_uart();
|
||||
let mut uart = uart::Uart::new_with_mio(
|
||||
dp.uart_1,
|
||||
uart::UartConfig::new_with_clk_config(uart_clk_config),
|
||||
(uart_tx, uart_rx),
|
||||
(gpio_pins.mio.mio48, gpio_pins.mio.mio49),
|
||||
)
|
||||
.unwrap();
|
||||
uart.write_all(b"-- Zynq 7000 Zedboard I2C L3GD20H example --\n\r")
|
||||
@ -95,45 +93,48 @@ async fn main(_spawner: Spawner) -> ! {
|
||||
let boot_mode = BootMode::new();
|
||||
info!("Boot mode: {:?}", boot_mode);
|
||||
|
||||
let sck_pin = gpio_pins.mio.mio12.into_i2c();
|
||||
let sda_pin = gpio_pins.mio.mio13.into_i2c();
|
||||
let pin_sel = match I2C_ADDR_SEL {
|
||||
I2cAddr::Sa0Low => PinState::Low,
|
||||
I2cAddr::Sa0High => PinState::High,
|
||||
};
|
||||
let _sa0_pin = gpio_pins.mio.mio11.into_output(pin_sel);
|
||||
let _sa0_pin = Output::new_for_mio(gpio_pins.mio.mio11, pin_sel);
|
||||
// The CS pin must be pulled high.
|
||||
let _cs_pin = gpio_pins.mio.mio10.into_output(PinState::High);
|
||||
let _cs_pin = Output::new_for_mio(gpio_pins.mio.mio10, PinState::High);
|
||||
|
||||
let clk_config = i2c::calculate_divisors(
|
||||
clocks.arm_clocks().cpu_1x_clk(),
|
||||
i2c::I2cSpeed::Normal100kHz,
|
||||
)
|
||||
.unwrap();
|
||||
let i2c = i2c::I2c::new_with_mio(dp.i2c_1, clk_config, (sck_pin, sda_pin)).unwrap();
|
||||
let i2c = i2c::I2c::new_with_mio(
|
||||
dp.i2c_1,
|
||||
clk_config,
|
||||
(gpio_pins.mio.mio12, gpio_pins.mio.mio13),
|
||||
)
|
||||
.unwrap();
|
||||
let mut l3gd20 = l3gd20::i2c::L3gd20::new(i2c, l3gd20::i2c::I2cAddr::Sa0Low).unwrap();
|
||||
let who_am_i = l3gd20.who_am_i().unwrap();
|
||||
info!("L3GD20 WHO_AM_I: 0x{:02X}", who_am_i);
|
||||
|
||||
let mut delay = Delay;
|
||||
let mut ticker = Ticker::every(Duration::from_millis(400));
|
||||
let mut mio_led = gpio_pins.mio.mio7.into_output(PinState::Low);
|
||||
let mut mio_led = Output::new_for_mio(gpio_pins.mio.mio7, PinState::Low);
|
||||
|
||||
let mut emio_leds: [EmioPin; 8] = [
|
||||
gpio_pins.emio.take(0).unwrap(),
|
||||
gpio_pins.emio.take(1).unwrap(),
|
||||
gpio_pins.emio.take(2).unwrap(),
|
||||
gpio_pins.emio.take(3).unwrap(),
|
||||
gpio_pins.emio.take(4).unwrap(),
|
||||
gpio_pins.emio.take(5).unwrap(),
|
||||
gpio_pins.emio.take(6).unwrap(),
|
||||
gpio_pins.emio.take(7).unwrap(),
|
||||
let mut emio_leds: [Output; 8] = [
|
||||
Output::new_for_emio(gpio_pins.emio.take(0).unwrap(), PinState::Low),
|
||||
Output::new_for_emio(gpio_pins.emio.take(1).unwrap(), PinState::Low),
|
||||
Output::new_for_emio(gpio_pins.emio.take(2).unwrap(), PinState::Low),
|
||||
Output::new_for_emio(gpio_pins.emio.take(3).unwrap(), PinState::Low),
|
||||
Output::new_for_emio(gpio_pins.emio.take(4).unwrap(), PinState::Low),
|
||||
Output::new_for_emio(gpio_pins.emio.take(5).unwrap(), PinState::Low),
|
||||
Output::new_for_emio(gpio_pins.emio.take(6).unwrap(), PinState::Low),
|
||||
Output::new_for_emio(gpio_pins.emio.take(7).unwrap(), PinState::Low),
|
||||
];
|
||||
for (idx, led) in emio_leds.iter_mut().enumerate() {
|
||||
if idx % 2 == 0 {
|
||||
led.into_output(PinState::High);
|
||||
led.set_high();
|
||||
} else {
|
||||
led.into_output(PinState::Low);
|
||||
led.set_low();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,7 @@ use zynq7000_hal::{
|
||||
clocks::Clocks,
|
||||
configure_level_shifter,
|
||||
gic::{GicConfigurator, GicInterruptHelper, Interrupt},
|
||||
gpio::{DynMioPin, EmioPin, GpioPins, PinState},
|
||||
gpio::{GpioPins, Output, PinState},
|
||||
gtc::Gtc,
|
||||
spi::{self, SpiAsync, SpiId, SpiWithHwCs, SpiWithHwCsAsync, on_interrupt},
|
||||
time::Hertz,
|
||||
@ -82,12 +82,10 @@ async fn main(spawner: Spawner) -> ! {
|
||||
let uart_clk_config = uart::ClkConfigRaw::new_autocalc_with_error(clocks.io_clocks(), 115200)
|
||||
.unwrap()
|
||||
.0;
|
||||
let uart_tx = gpio_pins.mio.mio48.into_uart();
|
||||
let uart_rx = gpio_pins.mio.mio49.into_uart();
|
||||
let mut uart = uart::Uart::new_with_mio(
|
||||
dp.uart_1,
|
||||
uart::UartConfig::new_with_clk_config(uart_clk_config),
|
||||
(uart_tx, uart_rx),
|
||||
(gpio_pins.mio.mio48, gpio_pins.mio.mio49),
|
||||
)
|
||||
.unwrap();
|
||||
uart.write_all(b"-- Zynq 7000 Zedboard SPI L3GD20H example --\n\r")
|
||||
@ -106,10 +104,6 @@ async fn main(spawner: Spawner) -> ! {
|
||||
spi_ref_clk_div
|
||||
);
|
||||
}
|
||||
let sck_pin = gpio_pins.mio.mio12.into_spi();
|
||||
let mosi_pin = gpio_pins.mio.mio10.into_spi();
|
||||
let miso_pin = gpio_pins.mio.mio11.into_spi();
|
||||
let ss_pin = gpio_pins.mio.mio13.into_spi();
|
||||
|
||||
let mut spi = spi::Spi::new_one_hw_cs(
|
||||
dp.spi_1,
|
||||
@ -121,8 +115,12 @@ async fn main(spawner: Spawner) -> ! {
|
||||
embedded_hal::spi::MODE_3,
|
||||
spi::SlaveSelectConfig::AutoWithAutoStart,
|
||||
),
|
||||
(sck_pin, mosi_pin, miso_pin),
|
||||
ss_pin,
|
||||
(
|
||||
gpio_pins.mio.mio12,
|
||||
gpio_pins.mio.mio10,
|
||||
gpio_pins.mio.mio11,
|
||||
),
|
||||
gpio_pins.mio.mio13,
|
||||
)
|
||||
.unwrap();
|
||||
let mod_id = spi.regs().read_mod_id();
|
||||
@ -138,24 +136,25 @@ async fn main(spawner: Spawner) -> ! {
|
||||
.build(),
|
||||
);
|
||||
|
||||
let mio_led = gpio_pins.mio.mio7.into_output(PinState::Low).downgrade();
|
||||
let mut emio_leds: [EmioPin; 8] = [
|
||||
gpio_pins.emio.take(0).unwrap(),
|
||||
gpio_pins.emio.take(1).unwrap(),
|
||||
gpio_pins.emio.take(2).unwrap(),
|
||||
gpio_pins.emio.take(3).unwrap(),
|
||||
gpio_pins.emio.take(4).unwrap(),
|
||||
gpio_pins.emio.take(5).unwrap(),
|
||||
gpio_pins.emio.take(6).unwrap(),
|
||||
gpio_pins.emio.take(7).unwrap(),
|
||||
let mio_led = Output::new_for_mio(gpio_pins.mio.mio7, PinState::Low);
|
||||
let mut emio_leds: [Output; 8] = [
|
||||
Output::new_for_emio(gpio_pins.emio.take(0).unwrap(), PinState::Low),
|
||||
Output::new_for_emio(gpio_pins.emio.take(1).unwrap(), PinState::Low),
|
||||
Output::new_for_emio(gpio_pins.emio.take(2).unwrap(), PinState::Low),
|
||||
Output::new_for_emio(gpio_pins.emio.take(3).unwrap(), PinState::Low),
|
||||
Output::new_for_emio(gpio_pins.emio.take(4).unwrap(), PinState::Low),
|
||||
Output::new_for_emio(gpio_pins.emio.take(5).unwrap(), PinState::Low),
|
||||
Output::new_for_emio(gpio_pins.emio.take(6).unwrap(), PinState::Low),
|
||||
Output::new_for_emio(gpio_pins.emio.take(7).unwrap(), PinState::Low),
|
||||
];
|
||||
for (idx, led) in emio_leds.iter_mut().enumerate() {
|
||||
if idx % 2 == 0 {
|
||||
led.into_output(PinState::High);
|
||||
led.set_high();
|
||||
} else {
|
||||
led.into_output(PinState::Low);
|
||||
led.set_low();
|
||||
}
|
||||
}
|
||||
|
||||
spawner.spawn(logger_task(uart)).unwrap();
|
||||
if BLOCKING {
|
||||
blocking_application(mio_led, emio_leds, spi).await;
|
||||
@ -178,8 +177,8 @@ pub async fn logger_task(uart: uart::Uart) {
|
||||
}
|
||||
|
||||
pub async fn blocking_application(
|
||||
mut mio_led: DynMioPin,
|
||||
mut emio_leds: [EmioPin; 8],
|
||||
mut mio_led: Output,
|
||||
mut emio_leds: [Output; 8],
|
||||
spi: spi::Spi,
|
||||
) -> ! {
|
||||
let mut delay = Delay;
|
||||
@ -207,8 +206,8 @@ pub async fn blocking_application(
|
||||
}
|
||||
|
||||
pub async fn non_blocking_application(
|
||||
mut mio_led: DynMioPin,
|
||||
mut emio_leds: [EmioPin; 8],
|
||||
mut mio_led: Output,
|
||||
mut emio_leds: [Output; 8],
|
||||
spi: spi::Spi,
|
||||
) -> ! {
|
||||
let mut delay = Delay;
|
||||
|
@ -17,7 +17,7 @@ use zynq7000_hal::{
|
||||
clocks::Clocks,
|
||||
configure_level_shifter,
|
||||
gic::{GicConfigurator, GicInterruptHelper, Interrupt},
|
||||
gpio::{EmioPin, GpioPins, PinState},
|
||||
gpio::{GpioPins, Output, PinState},
|
||||
gtc::Gtc,
|
||||
uart::{ClkConfigRaw, Uart, UartConfig},
|
||||
};
|
||||
@ -50,13 +50,13 @@ pub enum UartSel {
|
||||
}
|
||||
|
||||
pub struct UartMultiplexer {
|
||||
sel_pins: [EmioPin; 3],
|
||||
sel_pins: [Output; 3],
|
||||
}
|
||||
|
||||
impl UartMultiplexer {
|
||||
pub fn new(mut sel_pins: [EmioPin; 3]) -> Self {
|
||||
pub fn new(mut sel_pins: [Output; 3]) -> Self {
|
||||
for pin in sel_pins.iter_mut() {
|
||||
pin.into_output(PinState::Low);
|
||||
pin.set_low();
|
||||
}
|
||||
Self { sel_pins }
|
||||
}
|
||||
@ -65,34 +65,34 @@ impl UartMultiplexer {
|
||||
// TODO: A pin group switcher would be nice to do this in one go.
|
||||
match sel {
|
||||
UartSel::Uart0 => {
|
||||
self.sel_pins[2].set_low().unwrap();
|
||||
self.sel_pins[1].set_low().unwrap();
|
||||
self.sel_pins[0].set_low().unwrap();
|
||||
self.sel_pins[2].set_low();
|
||||
self.sel_pins[1].set_low();
|
||||
self.sel_pins[0].set_low();
|
||||
}
|
||||
UartSel::Uartlite => {
|
||||
self.sel_pins[2].set_low().unwrap();
|
||||
self.sel_pins[1].set_low().unwrap();
|
||||
self.sel_pins[0].set_high().unwrap();
|
||||
self.sel_pins[2].set_low();
|
||||
self.sel_pins[1].set_low();
|
||||
self.sel_pins[0].set_high();
|
||||
}
|
||||
UartSel::Uart16550 => {
|
||||
self.sel_pins[2].set_low().unwrap();
|
||||
self.sel_pins[1].set_high().unwrap();
|
||||
self.sel_pins[0].set_low().unwrap();
|
||||
self.sel_pins[2].set_low();
|
||||
self.sel_pins[1].set_high();
|
||||
self.sel_pins[0].set_low();
|
||||
}
|
||||
UartSel::Uart0ToUartlite => {
|
||||
self.sel_pins[2].set_low().unwrap();
|
||||
self.sel_pins[1].set_high().unwrap();
|
||||
self.sel_pins[0].set_high().unwrap();
|
||||
self.sel_pins[2].set_low();
|
||||
self.sel_pins[1].set_high();
|
||||
self.sel_pins[0].set_high();
|
||||
}
|
||||
UartSel::Uart0ToUart16550 => {
|
||||
self.sel_pins[2].set_high().unwrap();
|
||||
self.sel_pins[1].set_low().unwrap();
|
||||
self.sel_pins[0].set_low().unwrap();
|
||||
self.sel_pins[2].set_high();
|
||||
self.sel_pins[1].set_low();
|
||||
self.sel_pins[0].set_low();
|
||||
}
|
||||
UartSel::UartliteToUart16550 => {
|
||||
self.sel_pins[2].set_high().unwrap();
|
||||
self.sel_pins[1].set_low().unwrap();
|
||||
self.sel_pins[0].set_high().unwrap();
|
||||
self.sel_pins[2].set_high();
|
||||
self.sel_pins[1].set_low();
|
||||
self.sel_pins[0].set_high();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -123,12 +123,10 @@ async fn main(_spawner: Spawner) -> ! {
|
||||
let uart_clk_config = ClkConfigRaw::new_autocalc_with_error(clocks.io_clocks(), 115200)
|
||||
.unwrap()
|
||||
.0;
|
||||
let uart_tx = gpio_pins.mio.mio48.into_uart();
|
||||
let uart_rx = gpio_pins.mio.mio49.into_uart();
|
||||
let mut log_uart = Uart::new_with_mio(
|
||||
dp.uart_1,
|
||||
UartConfig::new_with_clk_config(uart_clk_config),
|
||||
(uart_tx, uart_rx),
|
||||
(gpio_pins.mio.mio48, gpio_pins.mio.mio49),
|
||||
)
|
||||
.unwrap();
|
||||
log_uart.write_all(INIT_STRING.as_bytes()).unwrap();
|
||||
@ -163,26 +161,23 @@ async fn main(_spawner: Spawner) -> ! {
|
||||
info!("Boot mode: {:?}", boot_mode);
|
||||
|
||||
let mut ticker = Ticker::every(Duration::from_millis(1000));
|
||||
let mut mio_led = gpio_pins.mio.mio7.into_output(PinState::Low);
|
||||
|
||||
let mut emio_leds: [EmioPin; 8] = [
|
||||
gpio_pins.emio.take(0).unwrap(),
|
||||
gpio_pins.emio.take(1).unwrap(),
|
||||
gpio_pins.emio.take(2).unwrap(),
|
||||
gpio_pins.emio.take(3).unwrap(),
|
||||
gpio_pins.emio.take(4).unwrap(),
|
||||
gpio_pins.emio.take(5).unwrap(),
|
||||
gpio_pins.emio.take(6).unwrap(),
|
||||
gpio_pins.emio.take(7).unwrap(),
|
||||
let mut mio_led = Output::new_for_mio(gpio_pins.mio.mio7, PinState::Low);
|
||||
let mut emio_leds: [Output; 8] = [
|
||||
Output::new_for_emio(gpio_pins.emio.take(0).unwrap(), PinState::Low),
|
||||
Output::new_for_emio(gpio_pins.emio.take(1).unwrap(), PinState::Low),
|
||||
Output::new_for_emio(gpio_pins.emio.take(2).unwrap(), PinState::Low),
|
||||
Output::new_for_emio(gpio_pins.emio.take(3).unwrap(), PinState::Low),
|
||||
Output::new_for_emio(gpio_pins.emio.take(4).unwrap(), PinState::Low),
|
||||
Output::new_for_emio(gpio_pins.emio.take(5).unwrap(), PinState::Low),
|
||||
Output::new_for_emio(gpio_pins.emio.take(6).unwrap(), PinState::Low),
|
||||
Output::new_for_emio(gpio_pins.emio.take(7).unwrap(), PinState::Low),
|
||||
];
|
||||
for led in emio_leds.iter_mut() {
|
||||
led.into_output(PinState::Low);
|
||||
}
|
||||
|
||||
let mut uart_mux = UartMultiplexer::new([
|
||||
gpio_pins.emio.take(8).unwrap(),
|
||||
gpio_pins.emio.take(9).unwrap(),
|
||||
gpio_pins.emio.take(10).unwrap(),
|
||||
Output::new_for_emio(gpio_pins.emio.take(8).unwrap(), PinState::Low),
|
||||
Output::new_for_emio(gpio_pins.emio.take(9).unwrap(), PinState::Low),
|
||||
Output::new_for_emio(gpio_pins.emio.take(10).unwrap(), PinState::Low),
|
||||
]);
|
||||
let mut current_sel = UartSel::Uart0;
|
||||
uart_mux.select(current_sel);
|
||||
|
@ -43,7 +43,7 @@ use zynq7000_hal::{
|
||||
clocks::Clocks,
|
||||
configure_level_shifter,
|
||||
gic::{GicConfigurator, GicInterruptHelper, Interrupt},
|
||||
gpio::{EmioPin, GpioPins, Mio7, MioPin, Output, PinState},
|
||||
gpio::{GpioPins, Output, PinState},
|
||||
gtc::Gtc,
|
||||
time::Hertz,
|
||||
uart::{ClkConfigRaw, Uart, UartConfig},
|
||||
@ -114,13 +114,13 @@ pub enum UartSel {
|
||||
}
|
||||
|
||||
pub struct UartMultiplexer {
|
||||
sel_pins: [EmioPin; 3],
|
||||
sel_pins: [Output; 3],
|
||||
}
|
||||
|
||||
impl UartMultiplexer {
|
||||
pub fn new(mut sel_pins: [EmioPin; 3]) -> Self {
|
||||
pub fn new(mut sel_pins: [Output; 3]) -> Self {
|
||||
for pin in sel_pins.iter_mut() {
|
||||
pin.into_output(PinState::Low);
|
||||
pin.set_low();
|
||||
}
|
||||
Self { sel_pins }
|
||||
}
|
||||
@ -129,38 +129,39 @@ impl UartMultiplexer {
|
||||
// TODO: A pin group switcher would be nice to do this in one go.
|
||||
match sel {
|
||||
UartSel::Uart0 => {
|
||||
self.sel_pins[2].set_low().unwrap();
|
||||
self.sel_pins[1].set_low().unwrap();
|
||||
self.sel_pins[0].set_low().unwrap();
|
||||
self.sel_pins[2].set_low();
|
||||
self.sel_pins[1].set_low();
|
||||
self.sel_pins[0].set_low();
|
||||
}
|
||||
UartSel::Uartlite => {
|
||||
self.sel_pins[2].set_low().unwrap();
|
||||
self.sel_pins[1].set_low().unwrap();
|
||||
self.sel_pins[0].set_high().unwrap();
|
||||
self.sel_pins[2].set_low();
|
||||
self.sel_pins[1].set_low();
|
||||
self.sel_pins[0].set_high();
|
||||
}
|
||||
UartSel::Uart16550 => {
|
||||
self.sel_pins[2].set_low().unwrap();
|
||||
self.sel_pins[1].set_high().unwrap();
|
||||
self.sel_pins[0].set_low().unwrap();
|
||||
self.sel_pins[2].set_low();
|
||||
self.sel_pins[1].set_high();
|
||||
self.sel_pins[0].set_low();
|
||||
}
|
||||
UartSel::Uart0ToUartlite => {
|
||||
self.sel_pins[2].set_low().unwrap();
|
||||
self.sel_pins[1].set_high().unwrap();
|
||||
self.sel_pins[0].set_high().unwrap();
|
||||
self.sel_pins[2].set_low();
|
||||
self.sel_pins[1].set_high();
|
||||
self.sel_pins[0].set_high();
|
||||
}
|
||||
UartSel::Uart0ToUart16550 => {
|
||||
self.sel_pins[2].set_high().unwrap();
|
||||
self.sel_pins[1].set_low().unwrap();
|
||||
self.sel_pins[0].set_low().unwrap();
|
||||
self.sel_pins[2].set_high();
|
||||
self.sel_pins[1].set_low();
|
||||
self.sel_pins[0].set_low();
|
||||
}
|
||||
UartSel::UartliteToUart16550 => {
|
||||
self.sel_pins[2].set_high().unwrap();
|
||||
self.sel_pins[1].set_low().unwrap();
|
||||
self.sel_pins[0].set_high().unwrap();
|
||||
self.sel_pins[2].set_high();
|
||||
self.sel_pins[1].set_low();
|
||||
self.sel_pins[0].set_high();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[embassy_executor::main]
|
||||
#[unsafe(export_name = "main")]
|
||||
async fn main(spawner: Spawner) -> ! {
|
||||
@ -192,12 +193,10 @@ async fn main(spawner: Spawner) -> ! {
|
||||
let uart_clk_config = ClkConfigRaw::new_autocalc_with_error(clocks.io_clocks(), 115200)
|
||||
.unwrap()
|
||||
.0;
|
||||
let uart_tx = gpio_pins.mio.mio48.into_uart();
|
||||
let uart_rx = gpio_pins.mio.mio49.into_uart();
|
||||
let mut log_uart = Uart::new_with_mio(
|
||||
dp.uart_1,
|
||||
UartConfig::new_with_clk_config(uart_clk_config),
|
||||
(uart_tx, uart_rx),
|
||||
(gpio_pins.mio.mio48, gpio_pins.mio.mio49),
|
||||
)
|
||||
.unwrap();
|
||||
log_uart.write_all(INIT_STRING.as_bytes()).unwrap();
|
||||
@ -222,9 +221,9 @@ async fn main(spawner: Spawner) -> ! {
|
||||
|
||||
// Set up UART multiplexing before creating and configuring the UARTs.
|
||||
let mut uart_mux = UartMultiplexer::new([
|
||||
gpio_pins.emio.take(8).unwrap(),
|
||||
gpio_pins.emio.take(9).unwrap(),
|
||||
gpio_pins.emio.take(10).unwrap(),
|
||||
Output::new_for_emio(gpio_pins.emio.take(8).unwrap(), PinState::Low),
|
||||
Output::new_for_emio(gpio_pins.emio.take(9).unwrap(), PinState::Low),
|
||||
Output::new_for_emio(gpio_pins.emio.take(10).unwrap(), PinState::Low),
|
||||
]);
|
||||
match UART_MODE {
|
||||
UartMode::Uart0ToUartlite => uart_mux.select(UartSel::Uart0ToUartlite),
|
||||
@ -254,21 +253,17 @@ async fn main(spawner: Spawner) -> ! {
|
||||
let boot_mode = BootMode::new();
|
||||
info!("Boot mode: {:?}", boot_mode);
|
||||
|
||||
let mio_led = gpio_pins.mio.mio7.into_output(PinState::Low);
|
||||
|
||||
let mut emio_leds: [EmioPin; 8] = [
|
||||
gpio_pins.emio.take(0).unwrap(),
|
||||
gpio_pins.emio.take(1).unwrap(),
|
||||
gpio_pins.emio.take(2).unwrap(),
|
||||
gpio_pins.emio.take(3).unwrap(),
|
||||
gpio_pins.emio.take(4).unwrap(),
|
||||
gpio_pins.emio.take(5).unwrap(),
|
||||
gpio_pins.emio.take(6).unwrap(),
|
||||
gpio_pins.emio.take(7).unwrap(),
|
||||
let mio_led = Output::new_for_mio(gpio_pins.mio.mio7, PinState::Low);
|
||||
let emio_leds: [Output; 8] = [
|
||||
Output::new_for_emio(gpio_pins.emio.take(0).unwrap(), PinState::Low),
|
||||
Output::new_for_emio(gpio_pins.emio.take(1).unwrap(), PinState::Low),
|
||||
Output::new_for_emio(gpio_pins.emio.take(2).unwrap(), PinState::Low),
|
||||
Output::new_for_emio(gpio_pins.emio.take(3).unwrap(), PinState::Low),
|
||||
Output::new_for_emio(gpio_pins.emio.take(4).unwrap(), PinState::Low),
|
||||
Output::new_for_emio(gpio_pins.emio.take(5).unwrap(), PinState::Low),
|
||||
Output::new_for_emio(gpio_pins.emio.take(6).unwrap(), PinState::Low),
|
||||
Output::new_for_emio(gpio_pins.emio.take(7).unwrap(), PinState::Low),
|
||||
];
|
||||
for led in emio_leds.iter_mut() {
|
||||
led.into_output(PinState::Low);
|
||||
}
|
||||
|
||||
let (uart_0_tx, mut uart_0_rx) = uart_0.split();
|
||||
let (uartlite_tx, _uartlite_rx) = uartlite.split();
|
||||
@ -353,7 +348,7 @@ fn build_print_string(prefix: &str, base_str: &str) -> alloc::string::String {
|
||||
}
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn led_task(mut mio_led: MioPin<Mio7, Output>, mut emio_leds: [EmioPin; 8]) {
|
||||
async fn led_task(mut mio_led: Output, mut emio_leds: [Output; 8]) {
|
||||
let mut ticker = Ticker::every(Duration::from_millis(1000));
|
||||
let mut led_idx = 0;
|
||||
loop {
|
||||
|
@ -14,7 +14,7 @@ use zynq7000_hal::{
|
||||
clocks::Clocks,
|
||||
configure_level_shifter,
|
||||
gic::{GicConfigurator, GicInterruptHelper, Interrupt},
|
||||
gpio::{EmioPin, GpioPins, PinState},
|
||||
gpio::{GpioPins, Output, PinState},
|
||||
gtc::Gtc,
|
||||
uart::{ClkConfigRaw, Uart, UartConfig},
|
||||
};
|
||||
@ -59,12 +59,10 @@ async fn main(_spawner: Spawner) -> ! {
|
||||
let uart_clk_config = ClkConfigRaw::new_autocalc_with_error(clocks.io_clocks(), 115200)
|
||||
.unwrap()
|
||||
.0;
|
||||
let uart_tx = gpio_pins.mio.mio48.into_uart();
|
||||
let uart_rx = gpio_pins.mio.mio49.into_uart();
|
||||
let mut uart = Uart::new_with_mio(
|
||||
dp.uart_1,
|
||||
UartConfig::new_with_clk_config(uart_clk_config),
|
||||
(uart_tx, uart_rx),
|
||||
(gpio_pins.mio.mio48, gpio_pins.mio.mio49),
|
||||
)
|
||||
.unwrap();
|
||||
uart.write_all(INIT_STRING.as_bytes()).unwrap();
|
||||
@ -81,21 +79,18 @@ async fn main(_spawner: Spawner) -> ! {
|
||||
info!("Boot mode: {:?}", boot_mode);
|
||||
|
||||
let mut ticker = Ticker::every(Duration::from_millis(200));
|
||||
let mut mio_led = gpio_pins.mio.mio7.into_output(PinState::Low);
|
||||
|
||||
let mut emio_leds: [EmioPin; 8] = [
|
||||
gpio_pins.emio.take(0).unwrap(),
|
||||
gpio_pins.emio.take(1).unwrap(),
|
||||
gpio_pins.emio.take(2).unwrap(),
|
||||
gpio_pins.emio.take(3).unwrap(),
|
||||
gpio_pins.emio.take(4).unwrap(),
|
||||
gpio_pins.emio.take(5).unwrap(),
|
||||
gpio_pins.emio.take(6).unwrap(),
|
||||
gpio_pins.emio.take(7).unwrap(),
|
||||
let mut mio_led = Output::new_for_mio(gpio_pins.mio.mio7, PinState::Low);
|
||||
let mut emio_leds: [Output; 8] = [
|
||||
Output::new_for_emio(gpio_pins.emio.take(0).unwrap(), PinState::Low),
|
||||
Output::new_for_emio(gpio_pins.emio.take(1).unwrap(), PinState::Low),
|
||||
Output::new_for_emio(gpio_pins.emio.take(2).unwrap(), PinState::Low),
|
||||
Output::new_for_emio(gpio_pins.emio.take(3).unwrap(), PinState::Low),
|
||||
Output::new_for_emio(gpio_pins.emio.take(4).unwrap(), PinState::Low),
|
||||
Output::new_for_emio(gpio_pins.emio.take(5).unwrap(), PinState::Low),
|
||||
Output::new_for_emio(gpio_pins.emio.take(6).unwrap(), PinState::Low),
|
||||
Output::new_for_emio(gpio_pins.emio.take(7).unwrap(), PinState::Low),
|
||||
];
|
||||
for led in emio_leds.iter_mut() {
|
||||
led.into_output(PinState::Low);
|
||||
}
|
||||
loop {
|
||||
mio_led.toggle().unwrap();
|
||||
|
||||
|
@ -11,7 +11,7 @@ keywords = ["no-std", "hal", "amd", "zynq7000", "xilinx", "bare-metal"]
|
||||
categories = ["embedded", "no-std", "hardware-support"]
|
||||
|
||||
[dependencies]
|
||||
cortex-ar = { path = "../../../Rust/cortex-ar/cortex-ar" }
|
||||
cortex-ar = { git = "https://github.com/rust-embedded/cortex-ar", branch = "main", features = ["critical-section-single-core"] }
|
||||
zynq7000 = { path = "../zynq7000" }
|
||||
|
||||
arbitrary-int = "1.3"
|
||||
|
@ -1,420 +0,0 @@
|
||||
//! Dynamic MIO pin module.
|
||||
//!
|
||||
//! This provides the type-erased MIO pin support.
|
||||
use arbitrary_int::{u2, u3};
|
||||
use zynq7000::gpio::{Gpio, MaskedOutput, MmioGpio};
|
||||
|
||||
pub use crate::gpio::PinState;
|
||||
use crate::slcr::Slcr;
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub struct MuxConf {
|
||||
l3: u3,
|
||||
l2: u2,
|
||||
l1: bool,
|
||||
l0: bool,
|
||||
}
|
||||
|
||||
impl From<zynq7000::slcr::mio::Config> for MuxConf {
|
||||
fn from(value: zynq7000::slcr::mio::Config) -> Self {
|
||||
Self::new(
|
||||
value.l0_sel(),
|
||||
value.l1_sel(),
|
||||
value.l2_sel(),
|
||||
value.l3_sel(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl MuxConf {
|
||||
#[inline]
|
||||
pub const fn new(l0: bool, l1: bool, l2: u2, l3: u3) -> Self {
|
||||
Self { l3, l2, l1, l0 }
|
||||
}
|
||||
|
||||
pub const fn new_with_l3(l3: u3) -> Self {
|
||||
Self::new(false, false, u2::new(0b00), l3)
|
||||
}
|
||||
|
||||
pub const fn new_for_gpio() -> Self {
|
||||
Self::new(false, false, u2::new(0), u3::new(0))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub const fn l0_sel(&self) -> bool {
|
||||
self.l0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub const fn l1_sel(&self) -> bool {
|
||||
self.l1
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub const fn l2_sel(&self) -> u2 {
|
||||
self.l2
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub const fn l3_sel(&self) -> u3 {
|
||||
self.l3
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub enum DynPinModeMio {
|
||||
Output,
|
||||
InputFloating,
|
||||
InputPullUp,
|
||||
IoPeriph(MuxConf),
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
#[error("invalid pin mode for MIO pin: {0:?}")]
|
||||
pub struct InvalidPinModeMio(pub DynPinModeMio);
|
||||
|
||||
impl embedded_hal::digital::Error for InvalidPinModeMio {
|
||||
fn kind(&self) -> embedded_hal::digital::ErrorKind {
|
||||
embedded_hal::digital::ErrorKind::Other
|
||||
}
|
||||
}
|
||||
|
||||
pub trait MioPinProvider {
|
||||
fn mode(&self) -> &DynPinModeMio;
|
||||
|
||||
fn offset(&self) -> usize;
|
||||
|
||||
#[inline]
|
||||
fn is_input(&self) -> bool {
|
||||
matches!(
|
||||
self.mode(),
|
||||
DynPinModeMio::InputFloating | DynPinModeMio::InputPullUp
|
||||
)
|
||||
}
|
||||
#[inline]
|
||||
fn is_output(&self) -> bool {
|
||||
matches!(self.mode(), DynPinModeMio::Output)
|
||||
}
|
||||
#[inline]
|
||||
fn is_io_periph(&self) -> bool {
|
||||
matches!(self.mode(), DynPinModeMio::IoPeriph(_))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct DynMioPin {
|
||||
offset: usize,
|
||||
dyn_mode: DynPinModeMio,
|
||||
regs: MmioGpio<'static>,
|
||||
}
|
||||
|
||||
impl MioPinProvider for DynMioPin {
|
||||
#[inline]
|
||||
fn mode(&self) -> &DynPinModeMio {
|
||||
&self.dyn_mode
|
||||
}
|
||||
#[inline]
|
||||
fn offset(&self) -> usize {
|
||||
self.offset
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
#[error("MIO pins 7 and 8 can only be output pins")]
|
||||
pub struct PinIsOutputOnly;
|
||||
|
||||
impl DynMioPin {
|
||||
#[inline]
|
||||
pub(crate) const fn new(offset: usize, dyn_mode: DynPinModeMio) -> Self {
|
||||
Self {
|
||||
offset,
|
||||
dyn_mode,
|
||||
regs: unsafe { Gpio::new_mmio_fixed() },
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert the pin into an output pin.
|
||||
pub fn into_output(&mut self, init_level: PinState) {
|
||||
self.dyn_mode = DynPinModeMio::Output;
|
||||
// The Pullup config does not matter for Output. Tri-state bit must be 0 for the
|
||||
// output driver to work.
|
||||
self.reconfigure_slcr_mio_cfg(false, None, Some(MuxConf::new_for_gpio()));
|
||||
match self.offset {
|
||||
0..=31 => {
|
||||
self.regs.bank_0().modify_dirm(|v| v | (1 << self.offset));
|
||||
self.regs.bank_0().modify_out_en(|v| v | (1 << self.offset));
|
||||
}
|
||||
32..=53 => {
|
||||
self.regs
|
||||
.bank_1()
|
||||
.modify_dirm(|v| v | 1 << (self.offset - 32));
|
||||
self.regs
|
||||
.bank_1()
|
||||
.modify_out_en(|v| v | 1 << (self.offset - 32));
|
||||
}
|
||||
_ => panic!("invalid GPIO pin offset"),
|
||||
}
|
||||
// Unwrap okay, just set mode.
|
||||
self.write_state(self.offset, init_level).unwrap();
|
||||
}
|
||||
|
||||
/// Convert the pin into a floating input pin.
|
||||
pub fn into_input_floating(&mut self) -> Result<(), PinIsOutputOnly> {
|
||||
if self.offset == 7 || self.offset == 8 {
|
||||
return Err(PinIsOutputOnly);
|
||||
}
|
||||
self.reconfigure_slcr_mio_cfg(true, Some(false), Some(MuxConf::new_for_gpio()));
|
||||
self.configure_input_pin();
|
||||
self.dyn_mode = DynPinModeMio::InputFloating;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Convert the pin into an input pin with a pull up.
|
||||
pub fn into_input_pull_up(&mut self) -> Result<(), PinIsOutputOnly> {
|
||||
if self.offset == 7 || self.offset == 8 {
|
||||
return Err(PinIsOutputOnly);
|
||||
}
|
||||
self.reconfigure_slcr_mio_cfg(true, Some(true), Some(MuxConf::new_for_gpio()));
|
||||
self.configure_input_pin();
|
||||
self.dyn_mode = DynPinModeMio::InputPullUp;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Convert the pin into an IO peripheral pin.
|
||||
pub fn into_io_periph_pin(&mut self, mux_conf: MuxConf, pullup: Option<bool>) {
|
||||
self.reconfigure_slcr_mio_cfg(false, pullup, Some(mux_conf));
|
||||
self.dyn_mode = DynPinModeMio::IoPeriph(mux_conf);
|
||||
}
|
||||
|
||||
pub fn is_low(&self) -> Result<bool, InvalidPinModeMio> {
|
||||
if !self.is_input() {
|
||||
return Err(InvalidPinModeMio(self.dyn_mode));
|
||||
}
|
||||
Ok(self.is_low_unchecked())
|
||||
}
|
||||
|
||||
/// This variant does not check whether the [DynPinModeMio] is correct.
|
||||
#[inline]
|
||||
pub fn is_low_unchecked(&self) -> bool {
|
||||
match self.offset {
|
||||
0..=31 => ((self.regs.read_in_0() >> self.offset) & 0b1) == 0,
|
||||
32..=53 => ((self.regs.read_in_1() >> (self.offset - 32)) & 0b1) == 0,
|
||||
_ => panic!("invalid GPIO pin offset"),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_high(&self) -> Result<bool, InvalidPinModeMio> {
|
||||
self.is_low().map(|v| !v)
|
||||
}
|
||||
|
||||
/// This variant does not check whether the [DynPinModeMio] is correct.
|
||||
#[inline]
|
||||
pub fn is_high_unchecked(&self) -> bool {
|
||||
!self.is_low_unchecked()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_set_low(&self) -> Result<bool, InvalidPinModeMio> {
|
||||
if !self.is_output() {
|
||||
return Err(InvalidPinModeMio(self.dyn_mode));
|
||||
}
|
||||
Ok(self.is_set_low_unchecked())
|
||||
}
|
||||
|
||||
/// This variant does not check whether the [DynPinModeMio] is correct.
|
||||
#[inline]
|
||||
pub fn is_set_low_unchecked(&self) -> bool {
|
||||
match self.offset {
|
||||
0..=31 => ((self.regs.read_out_0() >> self.offset) & 0b1) == 0,
|
||||
32..=53 => ((self.regs.read_out_1() >> (self.offset - 32)) & 0b1) == 0,
|
||||
_ => panic!("invalid GPIO pin offset"),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_set_high(&self) -> Result<bool, InvalidPinModeMio> {
|
||||
self.is_set_low().map(|v| !v)
|
||||
}
|
||||
|
||||
/// This variant does not check whether the [DynPinModeMio] is correct.
|
||||
#[inline]
|
||||
pub fn is_set_high_unchecked(&self) -> bool {
|
||||
!self.is_set_low_unchecked()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_low(&mut self) -> Result<(), InvalidPinModeMio> {
|
||||
self.write_state(self.offset, PinState::Low)
|
||||
}
|
||||
|
||||
/// This variant does not check whether the [DynPinModeMio] is correct.
|
||||
#[inline]
|
||||
pub fn set_low_unchecked(&mut self) {
|
||||
self.write_state_unchecked(self.offset, PinState::Low)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_high(&mut self) -> Result<(), InvalidPinModeMio> {
|
||||
self.write_state(self.offset, PinState::High)
|
||||
}
|
||||
|
||||
/// This variant does not check whether the [DynPinModeMio] is correct.
|
||||
#[inline]
|
||||
pub fn set_high_unchecked(&mut self) {
|
||||
self.write_state_unchecked(self.offset, PinState::High)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn offset_to_masked_out_ptr_and_ptr_offset(
|
||||
&mut self,
|
||||
offset: usize,
|
||||
) -> (usize, *mut MaskedOutput) {
|
||||
match offset {
|
||||
0..=15 => (offset, self.regs.pointer_to_masked_out_0_lsw()),
|
||||
16..=31 => (offset - 16, self.regs.pointer_to_masked_out_0_msw()),
|
||||
32..=47 => (offset - 32, self.regs.pointer_to_masked_out_1_lsw()),
|
||||
48..=53 => (offset - 48, self.regs.pointer_to_masked_out_1_msw()),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn write_state(&mut self, offset: usize, level: PinState) -> Result<(), InvalidPinModeMio> {
|
||||
if !self.is_output() {
|
||||
return Err(InvalidPinModeMio(self.dyn_mode));
|
||||
}
|
||||
self.write_state_unchecked(offset, level);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn write_state_unchecked(&mut self, offset: usize, level: PinState) {
|
||||
let (offset_in_reg, masked_out_ptr) = self.offset_to_masked_out_ptr_and_ptr_offset(offset);
|
||||
unsafe {
|
||||
core::ptr::write_volatile(
|
||||
masked_out_ptr,
|
||||
MaskedOutput::builder()
|
||||
.with_mask(!(1 << offset_in_reg))
|
||||
.with_output((level as u16) << offset_in_reg)
|
||||
.build(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_low_mut(&mut self) -> Result<bool, InvalidPinModeMio> {
|
||||
self.is_low()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_high_mut(&mut self) -> Result<bool, InvalidPinModeMio> {
|
||||
self.is_high()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_set_low_mut(&mut self) -> Result<bool, InvalidPinModeMio> {
|
||||
self.is_set_low()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_set_high_mut(&mut self) -> Result<bool, InvalidPinModeMio> {
|
||||
self.is_set_high()
|
||||
}
|
||||
|
||||
fn reconfigure_slcr_mio_cfg(
|
||||
&mut self,
|
||||
tristate: bool,
|
||||
pullup: Option<bool>,
|
||||
mux_conf: Option<MuxConf>,
|
||||
) {
|
||||
// Safety: We only modify the MIO config of the pin.
|
||||
let mut slcr_wrapper = unsafe { Slcr::steal() };
|
||||
// We read first, because writing also required unlocking the SLCR.
|
||||
// This allows the user to configure the SLCR themselves to avoid unnecessary
|
||||
// re-configuration which might also be potentially unsafe at run-time.
|
||||
let mio_cfg = slcr_wrapper.regs().read_mio_pins(self.offset).unwrap();
|
||||
if (pullup.is_some() && mio_cfg.pullup() != pullup.unwrap())
|
||||
|| (mux_conf.is_some() && MuxConf::from(mio_cfg) != mux_conf.unwrap())
|
||||
|| tristate != mio_cfg.tri_enable()
|
||||
{
|
||||
slcr_wrapper.modify(|mut_slcr| {
|
||||
mut_slcr
|
||||
.modify_mio_pins(self.offset, |mut val| {
|
||||
if let Some(pullup) = pullup {
|
||||
val.set_pullup(pullup);
|
||||
}
|
||||
if let Some(mux_conf) = mux_conf {
|
||||
val.set_l0_sel(mux_conf.l0_sel());
|
||||
val.set_l1_sel(mux_conf.l1_sel());
|
||||
val.set_l2_sel(mux_conf.l2_sel());
|
||||
val.set_l3_sel(mux_conf.l3_sel());
|
||||
}
|
||||
val.set_tri_enable(tristate);
|
||||
val
|
||||
})
|
||||
.unwrap();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn configure_input_pin(&mut self) {
|
||||
match self.offset {
|
||||
0..=31 => {
|
||||
self.regs.bank_0().modify_dirm(|mut v| {
|
||||
v &= !(1 << self.offset);
|
||||
v
|
||||
});
|
||||
self.regs.bank_0().modify_out_en(|mut v| {
|
||||
v &= !(1 << self.offset);
|
||||
v
|
||||
});
|
||||
}
|
||||
32..=53 => {
|
||||
self.regs.bank_1().modify_dirm(|mut v| {
|
||||
v &= !(1 << (self.offset - 32));
|
||||
v
|
||||
});
|
||||
self.regs.bank_1().modify_out_en(|mut v| {
|
||||
v &= !(1 << (self.offset - 32));
|
||||
v
|
||||
});
|
||||
}
|
||||
_ => panic!("invalid GPIO pin offset"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl embedded_hal::digital::ErrorType for DynMioPin {
|
||||
type Error = InvalidPinModeMio;
|
||||
}
|
||||
|
||||
impl embedded_hal::digital::OutputPin for DynMioPin {
|
||||
fn set_low(&mut self) -> Result<(), Self::Error> {
|
||||
self.set_low()?;
|
||||
Ok(())
|
||||
}
|
||||
fn set_high(&mut self) -> Result<(), Self::Error> {
|
||||
self.set_high()?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl embedded_hal::digital::StatefulOutputPin for DynMioPin {
|
||||
fn is_set_high(&mut self) -> Result<bool, Self::Error> {
|
||||
self.is_set_high_mut()
|
||||
}
|
||||
|
||||
fn is_set_low(&mut self) -> Result<bool, Self::Error> {
|
||||
self.is_set_low_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl embedded_hal::digital::InputPin for DynMioPin {
|
||||
fn is_high(&mut self) -> Result<bool, Self::Error> {
|
||||
self.is_high_mut()
|
||||
}
|
||||
|
||||
fn is_low(&mut self) -> Result<bool, Self::Error> {
|
||||
self.is_low_mut()
|
||||
}
|
||||
}
|
@ -1,263 +1,24 @@
|
||||
//! EMIO (Extended Multiplexed I/O) module.
|
||||
use zynq7000::gpio::{Gpio, MaskedOutput, MmioGpio};
|
||||
//! EMIO (Extended Multiplexed I/O) resource management module.
|
||||
use zynq7000::gpio::MmioGpio;
|
||||
|
||||
pub use crate::gpio::PinState;
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
#[error("invalid pin mode for MIO pin: {0:?}")]
|
||||
pub struct InvalidPinModeEmio(pub DynPinModeEmio);
|
||||
|
||||
impl embedded_hal::digital::Error for InvalidPinModeEmio {
|
||||
fn kind(&self) -> embedded_hal::digital::ErrorKind {
|
||||
embedded_hal::digital::ErrorKind::Other
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
||||
pub enum DynPinModeEmio {
|
||||
Output,
|
||||
Input,
|
||||
}
|
||||
|
||||
pub struct EmioPin {
|
||||
regs: MmioGpio<'static>,
|
||||
mode: DynPinModeEmio,
|
||||
offset: usize,
|
||||
}
|
||||
|
||||
impl EmioPin {
|
||||
/// Unsafely steal an EMIO input pin.
|
||||
///
|
||||
/// Unless you have no other option, it is recommended to use the [EmioPins::take] method
|
||||
/// to retrieve the pins safely. Returns [None] if the offset is larger than 63.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This allows potentially creating multiple input pin structures for the same GPIO
|
||||
/// peripheral which can cause data races.
|
||||
#[inline]
|
||||
pub const unsafe fn steal(offset: usize) -> Option<Self> {
|
||||
if offset >= 64 {
|
||||
return None;
|
||||
}
|
||||
Some(Self {
|
||||
regs: unsafe { Gpio::new_mmio_fixed() },
|
||||
mode: DynPinModeEmio::Input,
|
||||
offset: 0,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn into_input(&mut self) {
|
||||
self.mode = DynPinModeEmio::Input;
|
||||
match self.offset {
|
||||
0..=31 => {
|
||||
self.regs
|
||||
.bank_2()
|
||||
.modify_dirm(|val| val & !(1 << self.offset));
|
||||
}
|
||||
32..=63 => {
|
||||
self.regs
|
||||
.bank_3()
|
||||
.modify_dirm(|val| val & !(1 << self.offset));
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn into_output(&mut self, init_level: PinState) {
|
||||
self.mode = DynPinModeEmio::Output;
|
||||
match self.offset {
|
||||
0..=31 => {
|
||||
self.regs
|
||||
.bank_2()
|
||||
.modify_dirm(|val| val | (1 << self.offset));
|
||||
self.regs
|
||||
.bank_2()
|
||||
.modify_out_en(|val| val | (1 << self.offset));
|
||||
}
|
||||
32..=63 => {
|
||||
self.regs
|
||||
.bank_3()
|
||||
.modify_dirm(|val| val | (1 << self.offset));
|
||||
self.regs
|
||||
.bank_2()
|
||||
.modify_out_en(|val| val | (1 << self.offset));
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
// Unwrap okay, just set mode.
|
||||
self.write_state(self.offset, init_level).unwrap();
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_low(&self) -> Result<bool, InvalidPinModeEmio> {
|
||||
if self.mode == DynPinModeEmio::Output {
|
||||
return Err(InvalidPinModeEmio(self.mode));
|
||||
}
|
||||
Ok(self.is_low_unchecked())
|
||||
}
|
||||
|
||||
/// This variant does not check whether the [DynPinModeEmio] is correct.
|
||||
#[inline]
|
||||
pub fn is_low_unchecked(&self) -> bool {
|
||||
match self.offset {
|
||||
0..=31 => ((self.regs.read_in_0() >> self.offset) & 0b1) == 0,
|
||||
32..=63 => ((self.regs.read_in_1() >> (self.offset - 32)) & 0b1) == 0,
|
||||
_ => panic!("invalid GPIO pin offset"),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_high(&self) -> Result<bool, InvalidPinModeEmio> {
|
||||
self.is_low().map(|v| !v)
|
||||
}
|
||||
|
||||
/// This variant does not check whether the [DynPinModeEmio] is correct.
|
||||
#[inline]
|
||||
pub fn is_high_unchecked(&self) -> bool {
|
||||
!self.is_low_unchecked()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn offset_to_masked_out_ptr_and_ptr_offset(
|
||||
&mut self,
|
||||
offset: usize,
|
||||
) -> (usize, *mut MaskedOutput) {
|
||||
match offset {
|
||||
0..=15 => (offset, self.regs.pointer_to_masked_out_2_lsw()),
|
||||
16..=31 => (offset - 16, self.regs.pointer_to_masked_out_2_msw()),
|
||||
32..=47 => (offset - 32, self.regs.pointer_to_masked_out_3_lsw()),
|
||||
48..=63 => (offset - 48, self.regs.pointer_to_masked_out_3_msw()),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn write_state(&mut self, offset: usize, level: PinState) -> Result<(), InvalidPinModeEmio> {
|
||||
if self.mode == DynPinModeEmio::Input {
|
||||
return Err(InvalidPinModeEmio(self.mode));
|
||||
}
|
||||
self.write_state_unchecked(offset, level);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn write_state_unchecked(&mut self, offset: usize, level: PinState) {
|
||||
let (offset_in_reg, masked_out_ptr) = self.offset_to_masked_out_ptr_and_ptr_offset(offset);
|
||||
unsafe {
|
||||
core::ptr::write_volatile(
|
||||
masked_out_ptr,
|
||||
MaskedOutput::builder()
|
||||
.with_mask(!(1 << offset_in_reg))
|
||||
.with_output((level as u16) << offset_in_reg)
|
||||
.build(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_set_low(&mut self) -> Result<bool, InvalidPinModeEmio> {
|
||||
if self.mode == DynPinModeEmio::Input {
|
||||
return Err(InvalidPinModeEmio(self.mode));
|
||||
}
|
||||
Ok(self.is_set_low_unchecked())
|
||||
}
|
||||
|
||||
/// This variant does not check whether the [DynPinModeEmio] is correct.
|
||||
#[inline]
|
||||
pub fn is_set_low_unchecked(&mut self) -> bool {
|
||||
match self.offset {
|
||||
0..=31 => ((self.regs.read_out_2() >> self.offset) & 0b1) == 0,
|
||||
32..=64 => ((self.regs.read_out_3() >> (self.offset - 32)) & 0b1) == 0,
|
||||
_ => panic!("invalid GPIO pin offset"),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_set_high(&mut self) -> Result<bool, InvalidPinModeEmio> {
|
||||
self.is_set_low().map(|v| !v)
|
||||
}
|
||||
|
||||
/// This variant does not check whether the [DynPinModeEmio] is correct.
|
||||
#[inline]
|
||||
pub fn is_set_high_unchecked(&mut self) -> bool {
|
||||
!self.is_set_low_unchecked()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_high(&mut self) -> Result<(), InvalidPinModeEmio> {
|
||||
self.write_state(self.offset, PinState::High)
|
||||
}
|
||||
|
||||
/// This variant does not check whether the [DynPinModeEmio] is correct.
|
||||
#[inline]
|
||||
pub fn set_high_unchecked(&mut self) {
|
||||
self.write_state_unchecked(self.offset, PinState::High)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_low(&mut self) -> Result<(), InvalidPinModeEmio> {
|
||||
self.write_state(self.offset, PinState::Low)
|
||||
}
|
||||
|
||||
/// This variant does not check whether the [DynPinModeEmio] is correct.
|
||||
#[inline]
|
||||
pub fn set_low_unchecked(&mut self) {
|
||||
self.write_state_unchecked(self.offset, PinState::Low)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_high_mut(&mut self) -> Result<bool, InvalidPinModeEmio> {
|
||||
self.is_high()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_low_mut(&mut self) -> Result<bool, InvalidPinModeEmio> {
|
||||
self.is_low()
|
||||
/// This offset ranges from 0 to 64.
|
||||
pub fn offset(&self) -> usize {
|
||||
self.offset
|
||||
}
|
||||
}
|
||||
|
||||
impl embedded_hal::digital::ErrorType for EmioPin {
|
||||
type Error = InvalidPinModeEmio;
|
||||
}
|
||||
|
||||
impl embedded_hal::digital::InputPin for EmioPin {
|
||||
#[inline]
|
||||
fn is_high(&mut self) -> Result<bool, Self::Error> {
|
||||
self.is_high_mut()
|
||||
}
|
||||
#[inline]
|
||||
fn is_low(&mut self) -> Result<bool, Self::Error> {
|
||||
self.is_low_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl embedded_hal::digital::OutputPin for EmioPin {
|
||||
#[inline]
|
||||
fn set_high(&mut self) -> Result<(), Self::Error> {
|
||||
self.set_high()
|
||||
}
|
||||
#[inline]
|
||||
fn set_low(&mut self) -> Result<(), Self::Error> {
|
||||
self.set_low()
|
||||
}
|
||||
}
|
||||
|
||||
impl embedded_hal::digital::StatefulOutputPin for EmioPin {
|
||||
fn is_set_high(&mut self) -> Result<bool, Self::Error> {
|
||||
self.is_set_high()
|
||||
}
|
||||
|
||||
fn is_set_low(&mut self) -> Result<bool, Self::Error> {
|
||||
self.is_set_low()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct EmioPins {
|
||||
pub struct Pins {
|
||||
emios: [Option<EmioPin>; 64],
|
||||
}
|
||||
|
||||
impl EmioPins {
|
||||
impl Pins {
|
||||
/// Create a new EMIO pin structure.
|
||||
///
|
||||
/// This structure is supposed to be used as a singleton. It will configure all
|
||||
@ -270,12 +31,7 @@ impl EmioPins {
|
||||
mmio.bank_3().write_dirm(0);
|
||||
|
||||
(0..64).for_each(|i| {
|
||||
let mmio = unsafe { Gpio::new_mmio_fixed() };
|
||||
emios[i] = Some(EmioPin {
|
||||
regs: mmio,
|
||||
mode: DynPinModeEmio::Input,
|
||||
offset: i,
|
||||
});
|
||||
emios[i] = Some(EmioPin { offset: i });
|
||||
});
|
||||
Self { emios }
|
||||
}
|
||||
|
338
zynq7000-hal/src/gpio/ll.rs
Normal file
338
zynq7000-hal/src/gpio/ll.rs
Normal file
@ -0,0 +1,338 @@
|
||||
//! Low-level GPIO access module.
|
||||
use embedded_hal::digital::PinState;
|
||||
use zynq7000::gpio::{Gpio, MaskedOutput, MmioGpio};
|
||||
|
||||
use crate::slcr::Slcr;
|
||||
|
||||
use super::{PinIsOutputOnly, mio::MuxConf};
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum PinOffset {
|
||||
Mio(usize),
|
||||
Emio(usize),
|
||||
}
|
||||
|
||||
impl PinOffset {
|
||||
/// Returs [None] if offset is larger than 53.
|
||||
pub const fn new_for_mio(offset: usize) -> Option<Self> {
|
||||
if offset > 53 {
|
||||
return None;
|
||||
}
|
||||
Some(PinOffset::Mio(offset))
|
||||
}
|
||||
|
||||
/// Returs [None] if offset is larger than 63.
|
||||
pub const fn new_for_emio(offset: usize) -> Option<Self> {
|
||||
if offset > 63 {
|
||||
return None;
|
||||
}
|
||||
Some(PinOffset::Emio(offset))
|
||||
}
|
||||
|
||||
pub fn is_mio(&self) -> bool {
|
||||
match self {
|
||||
PinOffset::Mio(_) => true,
|
||||
PinOffset::Emio(_) => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PinOffset {
|
||||
pub fn offset(&self) -> usize {
|
||||
match self {
|
||||
PinOffset::Mio(offset) => *offset,
|
||||
PinOffset::Emio(offset) => *offset,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct LowLevelGpio {
|
||||
offset: PinOffset,
|
||||
regs: MmioGpio<'static>,
|
||||
}
|
||||
|
||||
impl LowLevelGpio {
|
||||
pub fn new(offset: PinOffset) -> Self {
|
||||
Self {
|
||||
offset,
|
||||
regs: unsafe { Gpio::new_mmio_fixed() },
|
||||
}
|
||||
}
|
||||
|
||||
pub fn offset(&self) -> PinOffset {
|
||||
self.offset
|
||||
}
|
||||
|
||||
/// Convert the pin into an output pin.
|
||||
pub fn configure_as_output_push_pull(&mut self, init_level: PinState) {
|
||||
let (offset, dirm, outen) = self.get_dirm_outen_regs_and_local_offset();
|
||||
if self.offset.is_mio() {
|
||||
// Tri-state bit must be 0 for the output driver to work.
|
||||
self.reconfigure_slcr_mio_cfg(false, None, Some(MuxConf::new_for_gpio()));
|
||||
}
|
||||
let mut curr_dirm = unsafe { core::ptr::read_volatile(dirm) };
|
||||
curr_dirm |= 1 << offset;
|
||||
unsafe { core::ptr::write_volatile(dirm, curr_dirm) };
|
||||
let mut curr_outen = unsafe { core::ptr::read_volatile(outen) };
|
||||
curr_outen |= 1 << offset;
|
||||
unsafe { core::ptr::write_volatile(outen, curr_outen) };
|
||||
// Unwrap okay, just set mode.
|
||||
self.write_state(init_level);
|
||||
}
|
||||
|
||||
/// Convert the pin into an output pin with open drain emulation.
|
||||
///
|
||||
/// This works by only enabling the output driver when the pin is driven low and letting
|
||||
/// the pin float when it is driven high. A pin pull-up is used for MIO pins as well which
|
||||
/// pulls the pin to a defined state if it is not driven. This allows something like 1-wire bus
|
||||
/// operation because other devices can pull the pin low as well.
|
||||
///
|
||||
/// For EMIO pins, the pull-up and the IO buffer necessary for open-drain usage must be
|
||||
/// provided by the FPGA design.
|
||||
pub fn configure_as_output_open_drain(&mut self, init_level: PinState) {
|
||||
let (offset, dirm, outen) = self.get_dirm_outen_regs_and_local_offset();
|
||||
if self.offset.is_mio() {
|
||||
// Tri-state bit must be 0 for the output driver to work. Enable the pullup pin.
|
||||
self.reconfigure_slcr_mio_cfg(false, Some(true), Some(MuxConf::new_for_gpio()));
|
||||
}
|
||||
let mut curr_dirm = unsafe { core::ptr::read_volatile(dirm) };
|
||||
curr_dirm |= 1 << offset;
|
||||
unsafe { core::ptr::write_volatile(dirm, curr_dirm) };
|
||||
// Disable the output driver depending on initial level.
|
||||
let mut curr_outen = unsafe { core::ptr::read_volatile(outen) };
|
||||
if init_level == PinState::High {
|
||||
curr_outen &= !(1 << offset);
|
||||
} else {
|
||||
curr_outen |= 1 << offset;
|
||||
}
|
||||
unsafe { core::ptr::write_volatile(outen, curr_outen) };
|
||||
// Unwrap okay, just set mode.
|
||||
self.write_state(init_level);
|
||||
}
|
||||
|
||||
/// Convert the pin into a floating input pin.
|
||||
pub fn configure_as_input_floating(&mut self) -> Result<(), PinIsOutputOnly> {
|
||||
if self.offset.is_mio() {
|
||||
let offset_raw = self.offset.offset();
|
||||
if offset_raw == 7 || offset_raw == 8 {
|
||||
return Err(PinIsOutputOnly);
|
||||
}
|
||||
self.reconfigure_slcr_mio_cfg(true, Some(false), Some(MuxConf::new_for_gpio()));
|
||||
}
|
||||
self.configure_input_pin();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Convert the pin into an input pin with a pull up.
|
||||
pub fn configure_as_input_with_pull_up(&mut self) -> Result<(), PinIsOutputOnly> {
|
||||
if self.offset.is_mio() {
|
||||
let offset_raw = self.offset.offset();
|
||||
if offset_raw == 7 || offset_raw == 8 {
|
||||
return Err(PinIsOutputOnly);
|
||||
}
|
||||
self.reconfigure_slcr_mio_cfg(true, Some(true), Some(MuxConf::new_for_gpio()));
|
||||
}
|
||||
self.configure_input_pin();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Convert the pin into an IO peripheral pin.
|
||||
pub fn configure_as_io_periph_pin(&mut self, mux_conf: MuxConf, pullup: Option<bool>) {
|
||||
self.reconfigure_slcr_mio_cfg(false, pullup, Some(mux_conf));
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_low(&self) -> bool {
|
||||
let (offset, in_reg) = self.get_data_in_reg_and_local_offset();
|
||||
let in_val = unsafe { core::ptr::read_volatile(in_reg) };
|
||||
((in_val >> offset) & 0b1) == 0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_high(&self) -> bool {
|
||||
!self.is_low()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_set_low(&self) -> bool {
|
||||
let (offset, out_reg) = self.get_data_out_reg_and_local_offset();
|
||||
let out_val = unsafe { core::ptr::read_volatile(out_reg) };
|
||||
((out_val >> offset) & 0b1) == 0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_set_high(&self) -> bool {
|
||||
!self.is_set_low()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn enable_output_driver(&mut self) {
|
||||
let (offset, _dirm, outen) = self.get_dirm_outen_regs_and_local_offset();
|
||||
let mut outen_reg = unsafe { core::ptr::read_volatile(outen) };
|
||||
outen_reg |= 1 << offset;
|
||||
unsafe { core::ptr::write_volatile(outen, outen_reg) };
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn disable_output_driver(&mut self) {
|
||||
let (offset, _dirm, outen) = self.get_dirm_outen_regs_and_local_offset();
|
||||
let mut outen_reg = unsafe { core::ptr::read_volatile(outen) };
|
||||
outen_reg &= !(1 << offset);
|
||||
unsafe { core::ptr::write_volatile(outen, outen_reg) };
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_low(&mut self) {
|
||||
self.write_state(PinState::Low)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_high(&mut self) {
|
||||
self.write_state(PinState::High)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn write_state(&mut self, level: PinState) {
|
||||
let (offset_in_reg, masked_out_ptr) = self.get_masked_out_reg_and_local_offset();
|
||||
unsafe {
|
||||
core::ptr::write_volatile(
|
||||
masked_out_ptr,
|
||||
MaskedOutput::builder()
|
||||
.with_mask(!(1 << offset_in_reg))
|
||||
.with_output((level as u16) << offset_in_reg)
|
||||
.build(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn reconfigure_slcr_mio_cfg(
|
||||
&mut self,
|
||||
tristate: bool,
|
||||
pullup: Option<bool>,
|
||||
mux_conf: Option<MuxConf>,
|
||||
) {
|
||||
let raw_offset = self.offset.offset();
|
||||
// Safety: We only modify the MIO config of the pin.
|
||||
let mut slcr_wrapper = unsafe { Slcr::steal() };
|
||||
// We read first, because writing also required unlocking the SLCR.
|
||||
// This allows the user to configure the SLCR themselves to avoid unnecessary
|
||||
// re-configuration which might also be potentially unsafe at run-time.
|
||||
let mio_cfg = slcr_wrapper.regs().read_mio_pins(raw_offset).unwrap();
|
||||
if (pullup.is_some() && mio_cfg.pullup() != pullup.unwrap())
|
||||
|| (mux_conf.is_some() && MuxConf::from(mio_cfg) != mux_conf.unwrap())
|
||||
|| tristate != mio_cfg.tri_enable()
|
||||
{
|
||||
slcr_wrapper.modify(|mut_slcr| {
|
||||
mut_slcr
|
||||
.modify_mio_pins(raw_offset, |mut val| {
|
||||
if let Some(pullup) = pullup {
|
||||
val.set_pullup(pullup);
|
||||
}
|
||||
if let Some(mux_conf) = mux_conf {
|
||||
val.set_l0_sel(mux_conf.l0_sel());
|
||||
val.set_l1_sel(mux_conf.l1_sel());
|
||||
val.set_l2_sel(mux_conf.l2_sel());
|
||||
val.set_l3_sel(mux_conf.l3_sel());
|
||||
}
|
||||
val.set_tri_enable(tristate);
|
||||
val
|
||||
})
|
||||
.unwrap();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn configure_input_pin(&mut self) {
|
||||
let (offset, dirm, outen) = self.get_dirm_outen_regs_and_local_offset();
|
||||
let mut curr_dirm = unsafe { core::ptr::read_volatile(dirm) };
|
||||
curr_dirm &= !(1 << offset);
|
||||
unsafe { core::ptr::write_volatile(dirm, curr_dirm) };
|
||||
let mut curr_outen = unsafe { core::ptr::read_volatile(outen) };
|
||||
curr_outen &= !(1 << offset);
|
||||
unsafe { core::ptr::write_volatile(outen, curr_outen) };
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn get_data_in_reg_and_local_offset(&self) -> (usize, *mut u32) {
|
||||
match self.offset {
|
||||
PinOffset::Mio(offset) => match offset {
|
||||
0..=31 => (offset, self.regs.pointer_to_in_0()),
|
||||
32..=53 => (offset - 32, self.regs.pointer_to_in_1()),
|
||||
_ => panic!("invalid MIO pin offset"),
|
||||
},
|
||||
PinOffset::Emio(offset) => match offset {
|
||||
0..=31 => (offset, self.regs.pointer_to_in_2()),
|
||||
32..=63 => (offset - 32, self.regs.pointer_to_in_3()),
|
||||
_ => panic!("invalid EMIO pin offset"),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn get_data_out_reg_and_local_offset(&self) -> (usize, *mut u32) {
|
||||
match self.offset {
|
||||
PinOffset::Mio(offset) => match offset {
|
||||
0..=31 => (offset, self.regs.pointer_to_out_0()),
|
||||
32..=53 => (offset - 32, self.regs.pointer_to_out_1()),
|
||||
_ => panic!("invalid MIO pin offset"),
|
||||
},
|
||||
PinOffset::Emio(offset) => match offset {
|
||||
0..=31 => (offset, self.regs.pointer_to_out_2()),
|
||||
32..=63 => (offset - 32, self.regs.pointer_to_out_3()),
|
||||
_ => panic!("invalid EMIO pin offset"),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn get_dirm_outen_regs_and_local_offset(&self) -> (usize, *mut u32, *mut u32) {
|
||||
match self.offset {
|
||||
PinOffset::Mio(offset) => match offset {
|
||||
0..=31 => (
|
||||
offset,
|
||||
self.regs.bank_0_shared().pointer_to_dirm(),
|
||||
self.regs.bank_0_shared().pointer_to_out_en(),
|
||||
),
|
||||
32..=53 => (
|
||||
offset - 32,
|
||||
self.regs.bank_1_shared().pointer_to_dirm(),
|
||||
self.regs.bank_1_shared().pointer_to_out_en(),
|
||||
),
|
||||
_ => panic!("invalid MIO pin offset"),
|
||||
},
|
||||
PinOffset::Emio(offset) => match offset {
|
||||
0..=31 => (
|
||||
offset,
|
||||
self.regs.bank_2_shared().pointer_to_dirm(),
|
||||
self.regs.bank_2_shared().pointer_to_out_en(),
|
||||
),
|
||||
32..=63 => (
|
||||
offset - 32,
|
||||
self.regs.bank_3_shared().pointer_to_dirm(),
|
||||
self.regs.bank_3_shared().pointer_to_out_en(),
|
||||
),
|
||||
_ => panic!("invalid EMIO pin offset"),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn get_masked_out_reg_and_local_offset(&mut self) -> (usize, *mut MaskedOutput) {
|
||||
match self.offset {
|
||||
PinOffset::Mio(offset) => match offset {
|
||||
0..=15 => (offset, self.regs.pointer_to_masked_out_0_lsw()),
|
||||
16..=31 => (offset - 16, self.regs.pointer_to_masked_out_0_msw()),
|
||||
32..=47 => (offset - 32, self.regs.pointer_to_masked_out_1_lsw()),
|
||||
48..=53 => (offset - 48, self.regs.pointer_to_masked_out_1_msw()),
|
||||
_ => panic!("invalid MIO pin offset"),
|
||||
},
|
||||
PinOffset::Emio(offset) => match offset {
|
||||
0..=15 => (offset, self.regs.pointer_to_masked_out_2_lsw()),
|
||||
16..=31 => (offset - 16, self.regs.pointer_to_masked_out_2_msw()),
|
||||
32..=47 => (offset - 32, self.regs.pointer_to_masked_out_3_lsw()),
|
||||
48..=63 => (offset - 48, self.regs.pointer_to_masked_out_3_msw()),
|
||||
_ => panic!("invalid EMIO pin offset"),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
@ -1,48 +1,64 @@
|
||||
//! Multiplexed I/O (MIO) module.
|
||||
//!
|
||||
//! This module provides a type-state API for all MIO pins. This also allows associating
|
||||
//! the pins, their modes and their IDs to the peripherals they are able to serve.
|
||||
//!
|
||||
//! The pins can be type-erased for easier handling, which also incurs some more run-time checks.
|
||||
//!
|
||||
//! # Examples
|
||||
//!
|
||||
//! - [Blinky](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/examples/simple/src/main.rs)
|
||||
//! - [Logger example](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/examples/simple/src/bin/logger.rs)
|
||||
//! which uses MIO pins for the UART.
|
||||
use embedded_hal::digital::InputPin;
|
||||
//! This module provides a [singleton][Pins] for the resource management of all MIO pins. This
|
||||
//! also allows associating the pins, their modes and their IDs to the peripherals they are able to
|
||||
//! serve.
|
||||
use arbitrary_int::{u2, u3};
|
||||
use zynq7000::gpio::MmioGpio;
|
||||
|
||||
use crate::sealed;
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub struct MuxConf {
|
||||
l3: u3,
|
||||
l2: u2,
|
||||
l1: bool,
|
||||
l0: bool,
|
||||
}
|
||||
|
||||
use super::{DynMioPin, DynPinModeMio, MioPinProvider, MuxConf, PinIsOutputOnly, PinState};
|
||||
impl From<zynq7000::slcr::mio::Config> for MuxConf {
|
||||
fn from(value: zynq7000::slcr::mio::Config) -> Self {
|
||||
Self::new(
|
||||
value.l0_sel(),
|
||||
value.l1_sel(),
|
||||
value.l2_sel(),
|
||||
value.l3_sel(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait PinMode: sealed::Sealed {}
|
||||
pub trait InputMode: sealed::Sealed {}
|
||||
impl MuxConf {
|
||||
#[inline]
|
||||
pub const fn new(l0: bool, l1: bool, l2: u2, l3: u3) -> Self {
|
||||
Self { l3, l2, l1, l0 }
|
||||
}
|
||||
|
||||
pub struct Output;
|
||||
pub const fn new_with_l3(l3: u3) -> Self {
|
||||
Self::new(false, false, u2::new(0b00), l3)
|
||||
}
|
||||
|
||||
impl PinMode for Output {}
|
||||
impl sealed::Sealed for Output {}
|
||||
pub const fn new_for_gpio() -> Self {
|
||||
Self::new(false, false, u2::new(0), u3::new(0))
|
||||
}
|
||||
|
||||
pub struct Input<S: InputMode>(core::marker::PhantomData<S>);
|
||||
#[inline]
|
||||
pub const fn l0_sel(&self) -> bool {
|
||||
self.l0
|
||||
}
|
||||
|
||||
impl<S: InputMode> PinMode for Input<S> {}
|
||||
impl<S: InputMode> sealed::Sealed for Input<S> {}
|
||||
#[inline]
|
||||
pub const fn l1_sel(&self) -> bool {
|
||||
self.l1
|
||||
}
|
||||
|
||||
pub struct PullUp;
|
||||
pub struct Floating;
|
||||
#[inline]
|
||||
pub const fn l2_sel(&self) -> u2 {
|
||||
self.l2
|
||||
}
|
||||
|
||||
impl InputMode for PullUp {}
|
||||
impl sealed::Sealed for PullUp {}
|
||||
impl InputMode for Floating {}
|
||||
impl sealed::Sealed for Floating {}
|
||||
|
||||
pub struct IoPeriph;
|
||||
impl sealed::Sealed for IoPeriph {}
|
||||
impl PinMode for IoPeriph {}
|
||||
|
||||
pub type Reset = Input<PullUp>;
|
||||
#[inline]
|
||||
pub const fn l3_sel(&self) -> u3 {
|
||||
self.l3
|
||||
}
|
||||
}
|
||||
|
||||
pub trait PinId {
|
||||
const OFFSET: usize;
|
||||
@ -141,29 +157,19 @@ pin_id!(Mio51, 51);
|
||||
pin_id!(Mio52, 52);
|
||||
pin_id!(Mio53, 53);
|
||||
|
||||
pub struct MioPin<I: PinId, S: PinMode> {
|
||||
inner: DynMioPin,
|
||||
phantom: core::marker::PhantomData<(I, S)>,
|
||||
pub trait MioPinMarker {
|
||||
fn offset(&self) -> usize;
|
||||
}
|
||||
|
||||
pub trait IoPeriphPin {
|
||||
fn mux_conf(&self) -> MuxConf;
|
||||
pub struct Pin<I: PinId> {
|
||||
phantom: core::marker::PhantomData<I>,
|
||||
}
|
||||
|
||||
impl<I: PinId, M: PinMode> MioPinProvider for MioPin<I, M> {
|
||||
delegate::delegate! {
|
||||
to self.inner {
|
||||
fn mode(&self) -> &DynPinModeMio;
|
||||
fn offset(&self) -> usize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: PinId, S: PinMode> MioPin<I, S> {
|
||||
impl<I: PinId> Pin<I> {
|
||||
#[inline]
|
||||
const unsafe fn new() -> Self {
|
||||
Self {
|
||||
inner: DynMioPin::new(I::OFFSET, DynPinModeMio::InputPullUp),
|
||||
//pin: LowLevelPin::new(I::OFFSET),
|
||||
phantom: core::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
@ -184,292 +190,175 @@ impl<I: PinId, S: PinMode> MioPin<I, S> {
|
||||
pub const unsafe fn steal() -> Self {
|
||||
unsafe { Self::new() }
|
||||
}
|
||||
|
||||
/// Convert the pin to the requested [`PinMode`]
|
||||
#[inline]
|
||||
pub fn into_mode<Mode: PinMode>(self) -> MioPin<I, Mode> {
|
||||
// Safe because we drop the existing Pin
|
||||
MioPin {
|
||||
inner: self.inner,
|
||||
phantom: core::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn into_floating_input(mut self) -> Result<MioPin<I, Input<Floating>>, PinIsOutputOnly> {
|
||||
self.inner.into_input_floating()?;
|
||||
Ok(self.into_mode())
|
||||
}
|
||||
|
||||
pub fn into_pull_up_input(mut self) -> Result<MioPin<I, Input<PullUp>>, PinIsOutputOnly> {
|
||||
self.inner.into_input_pull_up()?;
|
||||
Ok(self.into_mode())
|
||||
}
|
||||
|
||||
pub fn into_output(mut self, init_level: PinState) -> MioPin<I, Output> {
|
||||
self.inner.into_output(init_level);
|
||||
self.into_mode()
|
||||
}
|
||||
|
||||
pub fn into_io_periph(
|
||||
mut self,
|
||||
mux_conf: MuxConf,
|
||||
pullup: Option<bool>,
|
||||
) -> MioPin<I, IoPeriph> {
|
||||
self.inner.into_io_periph_pin(mux_conf, pullup);
|
||||
self.into_mode()
|
||||
}
|
||||
|
||||
/// Type-erase the pin.
|
||||
#[inline]
|
||||
pub const fn downgrade(self) -> DynMioPin {
|
||||
self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: PinId> MioPin<I, Output> {
|
||||
#[inline]
|
||||
pub fn set_high(&mut self) {
|
||||
self.inner.set_high_unchecked();
|
||||
}
|
||||
pub struct Pins {
|
||||
pub mio0: Pin<Mio0>,
|
||||
pub mio1: Pin<Mio1>,
|
||||
pub mio2: Pin<Mio2>,
|
||||
pub mio3: Pin<Mio3>,
|
||||
pub mio4: Pin<Mio4>,
|
||||
pub mio5: Pin<Mio5>,
|
||||
pub mio6: Pin<Mio6>,
|
||||
pub mio7: Pin<Mio7>,
|
||||
pub mio8: Pin<Mio8>,
|
||||
pub mio9: Pin<Mio9>,
|
||||
pub mio10: Pin<Mio10>,
|
||||
pub mio11: Pin<Mio11>,
|
||||
pub mio12: Pin<Mio12>,
|
||||
pub mio13: Pin<Mio13>,
|
||||
pub mio14: Pin<Mio14>,
|
||||
pub mio15: Pin<Mio15>,
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
pub mio16: Pin<Mio16>,
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
pub mio17: Pin<Mio17>,
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
pub mio18: Pin<Mio18>,
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
pub mio19: Pin<Mio19>,
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
pub mio20: Pin<Mio20>,
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
pub mio21: Pin<Mio21>,
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
pub mio22: Pin<Mio22>,
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
pub mio23: Pin<Mio23>,
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
pub mio24: Pin<Mio24>,
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
pub mio25: Pin<Mio25>,
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
pub mio26: Pin<Mio26>,
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
pub mio27: Pin<Mio27>,
|
||||
pub mio28: Pin<Mio28>,
|
||||
pub mio29: Pin<Mio29>,
|
||||
pub mio30: Pin<Mio30>,
|
||||
pub mio31: Pin<Mio31>,
|
||||
|
||||
#[inline]
|
||||
pub fn set_low(&mut self) {
|
||||
self.inner.set_low_unchecked();
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_set_high(&self) {
|
||||
self.inner.is_set_high_unchecked();
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_set_low(&self) {
|
||||
self.inner.is_set_low_unchecked();
|
||||
}
|
||||
pub mio32: Pin<Mio32>,
|
||||
pub mio33: Pin<Mio33>,
|
||||
pub mio34: Pin<Mio34>,
|
||||
pub mio35: Pin<Mio35>,
|
||||
pub mio36: Pin<Mio36>,
|
||||
pub mio37: Pin<Mio37>,
|
||||
pub mio38: Pin<Mio38>,
|
||||
pub mio39: Pin<Mio39>,
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
pub mio40: Pin<Mio40>,
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
pub mio41: Pin<Mio41>,
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
pub mio42: Pin<Mio42>,
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
pub mio43: Pin<Mio43>,
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
pub mio44: Pin<Mio44>,
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
pub mio45: Pin<Mio45>,
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
pub mio46: Pin<Mio46>,
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
pub mio47: Pin<Mio47>,
|
||||
pub mio48: Pin<Mio48>,
|
||||
pub mio49: Pin<Mio49>,
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
pub mio50: Pin<Mio50>,
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
pub mio51: Pin<Mio51>,
|
||||
pub mio52: Pin<Mio52>,
|
||||
pub mio53: Pin<Mio53>,
|
||||
}
|
||||
|
||||
impl<I: PinId> IoPeriphPin for MioPin<I, IoPeriph> {
|
||||
#[inline]
|
||||
fn mux_conf(&self) -> MuxConf {
|
||||
if let DynPinModeMio::IoPeriph(mux_conf) = self.inner.mode() {
|
||||
*mux_conf
|
||||
} else {
|
||||
// This should never happen due to type state guarantees.
|
||||
panic!("unexpected pin state");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: PinId, S: InputPin + PinMode> MioPin<I, S> {
|
||||
#[inline]
|
||||
pub fn is_high(&self) -> bool {
|
||||
self.inner.is_high_unchecked()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_low(&self) -> bool {
|
||||
self.inner.is_low_unchecked()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MioPins {
|
||||
pub mio0: MioPin<Mio0, Reset>,
|
||||
pub mio1: MioPin<Mio1, Reset>,
|
||||
pub mio2: MioPin<Mio2, Reset>,
|
||||
pub mio3: MioPin<Mio3, Reset>,
|
||||
pub mio4: MioPin<Mio4, Reset>,
|
||||
pub mio5: MioPin<Mio5, Reset>,
|
||||
pub mio6: MioPin<Mio6, Reset>,
|
||||
pub mio7: MioPin<Mio7, Output>,
|
||||
pub mio8: MioPin<Mio8, Output>,
|
||||
pub mio9: MioPin<Mio9, Reset>,
|
||||
pub mio10: MioPin<Mio10, Reset>,
|
||||
pub mio11: MioPin<Mio11, Reset>,
|
||||
pub mio12: MioPin<Mio12, Reset>,
|
||||
pub mio13: MioPin<Mio13, Reset>,
|
||||
pub mio14: MioPin<Mio14, Reset>,
|
||||
pub mio15: MioPin<Mio15, Reset>,
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
pub mio16: MioPin<Mio16, Reset>,
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
pub mio17: MioPin<Mio17, Reset>,
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
pub mio18: MioPin<Mio18, Reset>,
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
pub mio19: MioPin<Mio19, Reset>,
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
pub mio20: MioPin<Mio20, Reset>,
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
pub mio21: MioPin<Mio21, Reset>,
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
pub mio22: MioPin<Mio22, Reset>,
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
pub mio23: MioPin<Mio23, Reset>,
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
pub mio24: MioPin<Mio24, Reset>,
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
pub mio25: MioPin<Mio25, Reset>,
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
pub mio26: MioPin<Mio26, Reset>,
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
pub mio27: MioPin<Mio27, Reset>,
|
||||
pub mio28: MioPin<Mio28, Reset>,
|
||||
pub mio29: MioPin<Mio29, Reset>,
|
||||
pub mio30: MioPin<Mio30, Reset>,
|
||||
pub mio31: MioPin<Mio31, Reset>,
|
||||
|
||||
pub mio32: MioPin<Mio32, Reset>,
|
||||
pub mio33: MioPin<Mio33, Reset>,
|
||||
pub mio34: MioPin<Mio34, Reset>,
|
||||
pub mio35: MioPin<Mio35, Reset>,
|
||||
pub mio36: MioPin<Mio36, Reset>,
|
||||
pub mio37: MioPin<Mio37, Reset>,
|
||||
pub mio38: MioPin<Mio38, Reset>,
|
||||
pub mio39: MioPin<Mio39, Reset>,
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
pub mio40: MioPin<Mio40, Reset>,
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
pub mio41: MioPin<Mio41, Reset>,
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
pub mio42: MioPin<Mio42, Reset>,
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
pub mio43: MioPin<Mio43, Reset>,
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
pub mio44: MioPin<Mio44, Reset>,
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
pub mio45: MioPin<Mio45, Reset>,
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
pub mio46: MioPin<Mio46, Reset>,
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
pub mio47: MioPin<Mio47, Reset>,
|
||||
pub mio48: MioPin<Mio48, Reset>,
|
||||
pub mio49: MioPin<Mio49, Reset>,
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
pub mio50: MioPin<Mio50, Reset>,
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
pub mio51: MioPin<Mio51, Reset>,
|
||||
pub mio52: MioPin<Mio52, Reset>,
|
||||
pub mio53: MioPin<Mio53, Reset>,
|
||||
}
|
||||
|
||||
impl MioPins {
|
||||
impl Pins {
|
||||
pub const fn new(_mmio: MmioGpio) -> Self {
|
||||
Self {
|
||||
mio0: unsafe { MioPin::new() },
|
||||
mio1: unsafe { MioPin::new() },
|
||||
mio2: unsafe { MioPin::new() },
|
||||
mio3: unsafe { MioPin::new() },
|
||||
mio4: unsafe { MioPin::new() },
|
||||
mio5: unsafe { MioPin::new() },
|
||||
mio6: unsafe { MioPin::new() },
|
||||
mio7: unsafe { MioPin::new() },
|
||||
mio8: unsafe { MioPin::new() },
|
||||
mio9: unsafe { MioPin::new() },
|
||||
mio10: unsafe { MioPin::new() },
|
||||
mio11: unsafe { MioPin::new() },
|
||||
mio12: unsafe { MioPin::new() },
|
||||
mio13: unsafe { MioPin::new() },
|
||||
mio14: unsafe { MioPin::new() },
|
||||
mio15: unsafe { MioPin::new() },
|
||||
mio0: unsafe { Pin::new() },
|
||||
mio1: unsafe { Pin::new() },
|
||||
mio2: unsafe { Pin::new() },
|
||||
mio3: unsafe { Pin::new() },
|
||||
mio4: unsafe { Pin::new() },
|
||||
mio5: unsafe { Pin::new() },
|
||||
mio6: unsafe { Pin::new() },
|
||||
mio7: unsafe { Pin::new() },
|
||||
mio8: unsafe { Pin::new() },
|
||||
mio9: unsafe { Pin::new() },
|
||||
mio10: unsafe { Pin::new() },
|
||||
mio11: unsafe { Pin::new() },
|
||||
mio12: unsafe { Pin::new() },
|
||||
mio13: unsafe { Pin::new() },
|
||||
mio14: unsafe { Pin::new() },
|
||||
mio15: unsafe { Pin::new() },
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
mio16: unsafe { MioPin::new() },
|
||||
mio16: unsafe { Pin::new() },
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
mio17: unsafe { MioPin::new() },
|
||||
mio17: unsafe { Pin::new() },
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
mio18: unsafe { MioPin::new() },
|
||||
mio18: unsafe { Pin::new() },
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
mio19: unsafe { MioPin::new() },
|
||||
mio19: unsafe { Pin::new() },
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
mio20: unsafe { MioPin::new() },
|
||||
mio20: unsafe { Pin::new() },
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
mio21: unsafe { MioPin::new() },
|
||||
mio21: unsafe { Pin::new() },
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
mio22: unsafe { MioPin::new() },
|
||||
mio22: unsafe { Pin::new() },
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
mio23: unsafe { MioPin::new() },
|
||||
mio23: unsafe { Pin::new() },
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
mio24: unsafe { MioPin::new() },
|
||||
mio24: unsafe { Pin::new() },
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
mio25: unsafe { MioPin::new() },
|
||||
mio25: unsafe { Pin::new() },
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
mio26: unsafe { MioPin::new() },
|
||||
mio26: unsafe { Pin::new() },
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
mio27: unsafe { MioPin::new() },
|
||||
mio28: unsafe { MioPin::new() },
|
||||
mio29: unsafe { MioPin::new() },
|
||||
mio30: unsafe { MioPin::new() },
|
||||
mio31: unsafe { MioPin::new() },
|
||||
mio27: unsafe { Pin::new() },
|
||||
mio28: unsafe { Pin::new() },
|
||||
mio29: unsafe { Pin::new() },
|
||||
mio30: unsafe { Pin::new() },
|
||||
mio31: unsafe { Pin::new() },
|
||||
|
||||
mio32: unsafe { MioPin::new() },
|
||||
mio33: unsafe { MioPin::new() },
|
||||
mio34: unsafe { MioPin::new() },
|
||||
mio35: unsafe { MioPin::new() },
|
||||
mio36: unsafe { MioPin::new() },
|
||||
mio37: unsafe { MioPin::new() },
|
||||
mio38: unsafe { MioPin::new() },
|
||||
mio39: unsafe { MioPin::new() },
|
||||
mio32: unsafe { Pin::new() },
|
||||
mio33: unsafe { Pin::new() },
|
||||
mio34: unsafe { Pin::new() },
|
||||
mio35: unsafe { Pin::new() },
|
||||
mio36: unsafe { Pin::new() },
|
||||
mio37: unsafe { Pin::new() },
|
||||
mio38: unsafe { Pin::new() },
|
||||
mio39: unsafe { Pin::new() },
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
mio40: unsafe { MioPin::new() },
|
||||
mio40: unsafe { Pin::new() },
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
mio41: unsafe { MioPin::new() },
|
||||
mio41: unsafe { Pin::new() },
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
mio42: unsafe { MioPin::new() },
|
||||
mio42: unsafe { Pin::new() },
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
mio43: unsafe { MioPin::new() },
|
||||
mio43: unsafe { Pin::new() },
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
mio44: unsafe { MioPin::new() },
|
||||
mio44: unsafe { Pin::new() },
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
mio45: unsafe { MioPin::new() },
|
||||
mio45: unsafe { Pin::new() },
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
mio46: unsafe { MioPin::new() },
|
||||
mio46: unsafe { Pin::new() },
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
mio47: unsafe { MioPin::new() },
|
||||
mio48: unsafe { MioPin::new() },
|
||||
mio49: unsafe { MioPin::new() },
|
||||
mio47: unsafe { Pin::new() },
|
||||
mio48: unsafe { Pin::new() },
|
||||
mio49: unsafe { Pin::new() },
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
mio50: unsafe { MioPin::new() },
|
||||
mio50: unsafe { Pin::new() },
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
mio51: unsafe { MioPin::new() },
|
||||
mio52: unsafe { MioPin::new() },
|
||||
mio53: unsafe { MioPin::new() },
|
||||
mio51: unsafe { Pin::new() },
|
||||
mio52: unsafe { Pin::new() },
|
||||
mio53: unsafe { Pin::new() },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: PinId, M: PinMode> embedded_hal::digital::ErrorType for MioPin<I, M> {
|
||||
type Error = core::convert::Infallible;
|
||||
}
|
||||
|
||||
impl<I: PinId> embedded_hal::digital::OutputPin for MioPin<I, Output> {
|
||||
#[inline]
|
||||
fn set_low(&mut self) -> Result<(), Self::Error> {
|
||||
self.inner.set_low_unchecked();
|
||||
Ok(())
|
||||
}
|
||||
#[inline]
|
||||
fn set_high(&mut self) -> Result<(), Self::Error> {
|
||||
self.inner.set_high_unchecked();
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: PinId> embedded_hal::digital::StatefulOutputPin for MioPin<I, Output> {
|
||||
fn is_set_high(&mut self) -> Result<bool, Self::Error> {
|
||||
Ok(self.inner.is_set_high_unchecked())
|
||||
}
|
||||
|
||||
fn is_set_low(&mut self) -> Result<bool, Self::Error> {
|
||||
Ok(self.inner.is_set_low_unchecked())
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: PinId, M: InputMode + PinMode> embedded_hal::digital::InputPin for MioPin<I, M> {
|
||||
fn is_high(&mut self) -> Result<bool, Self::Error> {
|
||||
Ok(self.inner.is_high_unchecked())
|
||||
}
|
||||
|
||||
fn is_low(&mut self) -> Result<bool, Self::Error> {
|
||||
Ok(self.inner.is_low_unchecked())
|
||||
impl<I: PinId> MioPinMarker for Pin<I> {
|
||||
fn offset(&self) -> usize {
|
||||
I::OFFSET
|
||||
}
|
||||
}
|
||||
|
@ -1,27 +1,42 @@
|
||||
//! GPIO support module for the Zynq7000 SoC.
|
||||
pub mod dyn_mio;
|
||||
//!
|
||||
//! This module contains a MIO and EMIO pin resource managements singleton as well as abstractions
|
||||
//! to use these pins as GPIOs.
|
||||
//!
|
||||
//! # Examples
|
||||
//!
|
||||
//! - [Blinky](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/examples/simple/src/main.rs)
|
||||
//! - [Logger example](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/examples/simple/src/bin/logger.rs)
|
||||
//! which uses MIO pins for the UART.
|
||||
pub mod emio;
|
||||
pub mod ll;
|
||||
pub mod mio;
|
||||
|
||||
use crate::{enable_amba_peripheral_clock, slcr::Slcr};
|
||||
pub use dyn_mio::*;
|
||||
pub use emio::*;
|
||||
pub use mio::*;
|
||||
use core::convert::Infallible;
|
||||
use ll::PinOffset;
|
||||
use mio::{MioPinMarker, MuxConf};
|
||||
|
||||
use crate::gpio::ll::LowLevelGpio;
|
||||
use crate::{enable_amba_peripheral_clock, slcr::Slcr};
|
||||
pub use embedded_hal::digital::PinState;
|
||||
use zynq7000::{gpio::MmioGpio, slcr::reset::GpioClockReset};
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
#[error("MIO pins 7 and 8 can only be output pins")]
|
||||
pub struct PinIsOutputOnly;
|
||||
|
||||
/// GPIO pin singleton to allow resource management of both MIO and EMIO pins.
|
||||
pub struct GpioPins {
|
||||
pub mio: MioPins,
|
||||
pub emio: EmioPins,
|
||||
pub mio: mio::Pins,
|
||||
pub emio: emio::Pins,
|
||||
}
|
||||
|
||||
impl GpioPins {
|
||||
pub fn new(gpio: MmioGpio) -> Self {
|
||||
enable_amba_peripheral_clock(crate::PeripheralSelect::Gpio);
|
||||
Self {
|
||||
mio: MioPins::new(unsafe { gpio.clone() }),
|
||||
emio: EmioPins::new(gpio),
|
||||
mio: mio::Pins::new(unsafe { gpio.clone() }),
|
||||
emio: emio::Pins::new(gpio),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -40,3 +55,352 @@ pub fn reset() {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// Enumeration of all pin modes. Some of the modes are only valid for MIO pins.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub enum PinMode {
|
||||
OutputPushPull,
|
||||
/// See [super::gpio] documentation for more information on running an output pin in
|
||||
/// open-drain configuration.
|
||||
OutputOpenDrain,
|
||||
InputFloating,
|
||||
InputPullUp,
|
||||
/// MIO-only peripheral pin configuration
|
||||
MioIoPeriph(MuxConf),
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
#[error("invalid pin mode for MIO pin: {0:?}")]
|
||||
pub struct InvalidPinMode(pub PinMode);
|
||||
|
||||
impl embedded_hal::digital::Error for InvalidPinMode {
|
||||
fn kind(&self) -> embedded_hal::digital::ErrorKind {
|
||||
embedded_hal::digital::ErrorKind::Other
|
||||
}
|
||||
}
|
||||
|
||||
pub trait IoPinProvider {
|
||||
fn mode(&self) -> PinMode;
|
||||
|
||||
fn offset(&self) -> PinOffset;
|
||||
|
||||
#[inline]
|
||||
fn is_input(&self) -> bool {
|
||||
matches!(self.mode(), PinMode::InputFloating | PinMode::InputPullUp)
|
||||
}
|
||||
#[inline]
|
||||
fn is_output(&self) -> bool {
|
||||
matches!(
|
||||
self.mode(),
|
||||
PinMode::OutputPushPull | PinMode::OutputOpenDrain
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_io_periph(&self) -> bool {
|
||||
matches!(self.mode(), PinMode::MioIoPeriph(_))
|
||||
}
|
||||
}
|
||||
|
||||
/// Flex pin abstraction which can be dynamically re-configured.
|
||||
///
|
||||
/// The following functions can be configured at run-time:
|
||||
///
|
||||
/// - Input Floating
|
||||
/// - Input with Pull-Up
|
||||
/// - Output Push-Pull
|
||||
/// - Output Open-Drain.
|
||||
///
|
||||
/// Flex pins are always floating input pins after construction except for MIO7 and MIO8,
|
||||
/// which are Push-Pull Output pins with initial low-level.
|
||||
///
|
||||
/// ## Notes on [PinMode::OutputOpenDrain] configuration
|
||||
///
|
||||
/// For MIO, the open-drain functionality is simulated by only enabling the output driver
|
||||
/// when driving the pin low, and leaving the pin floating when the pin is driven high.
|
||||
/// The internal pull-up will also be enabled to have a high state if the pin is not driven.
|
||||
///
|
||||
/// For EMIO, the pull-up and the IO buffer needs to be provided in the FPGA design for the
|
||||
/// used EMIO pins because the EMIO pins are just wires going out to the FPGA design.
|
||||
/// The software will still perform the necessary logic when driving the pin low or high.
|
||||
///
|
||||
/// ## Notes on [PinMode::InputPullUp] configuration
|
||||
///
|
||||
/// For EMIO, the pull-up wiring needs to be provided by the FPGA design.
|
||||
pub struct Flex {
|
||||
ll: LowLevelGpio,
|
||||
mode: PinMode,
|
||||
}
|
||||
|
||||
impl Flex {
|
||||
pub fn new_for_mio<I: mio::PinId>(_pin: mio::Pin<I>) -> Self {
|
||||
let mut ll = LowLevelGpio::new(PinOffset::Mio(I::OFFSET));
|
||||
if I::OFFSET == 7 || I::OFFSET == 8 {
|
||||
ll.configure_as_output_push_pull(PinState::Low);
|
||||
} else {
|
||||
ll.configure_as_input_floating().unwrap();
|
||||
}
|
||||
Self {
|
||||
ll,
|
||||
mode: PinMode::InputFloating,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_for_emio(pin: emio::EmioPin) -> Self {
|
||||
let mut ll = LowLevelGpio::new(PinOffset::new_for_emio(pin.offset()).unwrap());
|
||||
ll.configure_as_input_floating().unwrap();
|
||||
Self {
|
||||
ll,
|
||||
mode: PinMode::InputFloating,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn configure_as_input_floating(&mut self) -> Result<(), PinIsOutputOnly> {
|
||||
self.mode = PinMode::InputFloating;
|
||||
self.ll.configure_as_input_floating()
|
||||
}
|
||||
|
||||
pub fn configure_as_input_with_pull_up(&mut self) -> Result<(), PinIsOutputOnly> {
|
||||
self.mode = PinMode::InputPullUp;
|
||||
self.ll.configure_as_input_with_pull_up()
|
||||
}
|
||||
|
||||
pub fn configure_as_output_push_pull(&mut self, level: PinState) {
|
||||
self.mode = PinMode::OutputPushPull;
|
||||
self.ll.configure_as_output_push_pull(level);
|
||||
}
|
||||
|
||||
pub fn configure_as_output_open_drain(&mut self, level: PinState) {
|
||||
self.mode = PinMode::OutputOpenDrain;
|
||||
self.ll.configure_as_output_open_drain(level);
|
||||
}
|
||||
|
||||
/// If the pin is configured as an input pin, this function does nothing.
|
||||
pub fn set_high(&mut self) {
|
||||
if self.is_input() {
|
||||
return;
|
||||
}
|
||||
if self.mode == PinMode::OutputOpenDrain {
|
||||
self.ll.disable_output_driver();
|
||||
} else {
|
||||
self.ll.set_high();
|
||||
}
|
||||
}
|
||||
|
||||
/// If the pin is configured as an input pin, this function does nothing.
|
||||
pub fn set_low(&mut self) {
|
||||
if self.is_input() {
|
||||
return;
|
||||
}
|
||||
if self.mode == PinMode::OutputOpenDrain {
|
||||
self.ll.enable_output_driver();
|
||||
}
|
||||
self.ll.set_low();
|
||||
}
|
||||
|
||||
/// Reads the input state of the pin, regardless of configured mode.
|
||||
#[inline]
|
||||
pub fn is_high(&self) -> bool {
|
||||
self.ll.is_high()
|
||||
}
|
||||
|
||||
/// Reads the input state of the pin, regardless of configured mode.
|
||||
#[inline]
|
||||
pub fn is_low(&self) -> bool {
|
||||
!self.ll.is_high()
|
||||
}
|
||||
|
||||
/// If the pin is not configured as a stateful output pin like Output Push-Pull, the result
|
||||
/// of this function is undefined.
|
||||
#[inline]
|
||||
pub fn is_set_low(&self) -> bool {
|
||||
self.ll.is_set_low()
|
||||
}
|
||||
|
||||
/// If the pin is not configured as a stateful output pin like Output Push-Pull, the result
|
||||
/// of this function is undefined.
|
||||
#[inline]
|
||||
pub fn is_set_high(&self) -> bool {
|
||||
!self.is_set_low()
|
||||
}
|
||||
}
|
||||
|
||||
impl IoPinProvider for Flex {
|
||||
fn mode(&self) -> PinMode {
|
||||
self.mode
|
||||
}
|
||||
|
||||
fn offset(&self) -> PinOffset {
|
||||
self.ll.offset()
|
||||
}
|
||||
}
|
||||
|
||||
impl embedded_hal::digital::ErrorType for Flex {
|
||||
type Error = Infallible;
|
||||
}
|
||||
|
||||
impl embedded_hal::digital::InputPin for Flex {
|
||||
/// Reads the input state of the pin, regardless of configured mode.
|
||||
#[inline]
|
||||
fn is_high(&mut self) -> Result<bool, Self::Error> {
|
||||
Ok(self.ll.is_high())
|
||||
}
|
||||
|
||||
/// Reads the input state of the pin, regardless of configured mode.
|
||||
#[inline]
|
||||
fn is_low(&mut self) -> Result<bool, Self::Error> {
|
||||
Ok(self.ll.is_high())
|
||||
}
|
||||
}
|
||||
|
||||
impl embedded_hal::digital::OutputPin for Flex {
|
||||
/// If the pin is configured as an input pin, this function does nothing.
|
||||
#[inline]
|
||||
fn set_low(&mut self) -> Result<(), Self::Error> {
|
||||
self.set_low();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// If the pin is configured as an input pin, this function does nothing.
|
||||
#[inline]
|
||||
fn set_high(&mut self) -> Result<(), Self::Error> {
|
||||
self.set_high();
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl embedded_hal::digital::StatefulOutputPin for Flex {
|
||||
/// If the pin is not configured as a stateful output pin like Output Push-Pull, the result
|
||||
/// of this function is undefined.
|
||||
#[inline]
|
||||
fn is_set_high(&mut self) -> Result<bool, Self::Error> {
|
||||
Ok(self.ll.is_set_high())
|
||||
}
|
||||
|
||||
/// If the pin is not configured as a stateful output pin like Output Push-Pull, the result
|
||||
/// of this function is undefined.
|
||||
#[inline]
|
||||
fn is_set_low(&mut self) -> Result<bool, Self::Error> {
|
||||
Ok(self.ll.is_set_low())
|
||||
}
|
||||
}
|
||||
|
||||
/// Push-Pull output pin.
|
||||
pub struct Output(LowLevelGpio);
|
||||
|
||||
impl Output {
|
||||
pub fn new_for_mio<I: mio::PinId>(_pin: mio::Pin<I>, init_level: PinState) -> Self {
|
||||
let mut low_level = LowLevelGpio::new(PinOffset::Mio(I::OFFSET));
|
||||
low_level.configure_as_output_push_pull(init_level);
|
||||
Self(low_level)
|
||||
}
|
||||
|
||||
pub fn new_for_emio(pin: emio::EmioPin, init_level: PinState) -> Self {
|
||||
let mut low_level = LowLevelGpio::new(PinOffset::new_for_emio(pin.offset()).unwrap());
|
||||
low_level.configure_as_output_push_pull(init_level);
|
||||
Self(low_level)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_low(&mut self) {
|
||||
self.0.set_low();
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_high(&mut self) {
|
||||
self.0.set_high();
|
||||
}
|
||||
}
|
||||
|
||||
impl embedded_hal::digital::ErrorType for Output {
|
||||
type Error = Infallible;
|
||||
}
|
||||
|
||||
impl embedded_hal::digital::OutputPin for Output {
|
||||
fn set_low(&mut self) -> Result<(), Self::Error> {
|
||||
self.0.set_low();
|
||||
Ok(())
|
||||
}
|
||||
fn set_high(&mut self) -> Result<(), Self::Error> {
|
||||
self.0.set_high();
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl embedded_hal::digital::StatefulOutputPin for Output {
|
||||
fn is_set_high(&mut self) -> Result<bool, Self::Error> {
|
||||
Ok(self.0.is_set_high())
|
||||
}
|
||||
|
||||
fn is_set_low(&mut self) -> Result<bool, Self::Error> {
|
||||
Ok(self.0.is_set_low())
|
||||
}
|
||||
}
|
||||
|
||||
/// Input pin.
|
||||
pub struct Input(LowLevelGpio);
|
||||
|
||||
impl Input {
|
||||
pub fn new_for_mio<I: mio::PinId>(_pin: mio::Pin<I>) -> Result<Self, PinIsOutputOnly> {
|
||||
let mut low_level = LowLevelGpio::new(PinOffset::Mio(I::OFFSET));
|
||||
low_level.configure_as_input_floating()?;
|
||||
Ok(Self(low_level))
|
||||
}
|
||||
|
||||
pub fn new_for_emio(pin: emio::EmioPin) -> Result<Self, PinIsOutputOnly> {
|
||||
let mut low_level = LowLevelGpio::new(PinOffset::new_for_emio(pin.offset()).unwrap());
|
||||
low_level.configure_as_input_floating()?;
|
||||
Ok(Self(low_level))
|
||||
}
|
||||
|
||||
pub fn is_high(&self) -> bool {
|
||||
self.0.is_high()
|
||||
}
|
||||
|
||||
pub fn is_low(&self) -> bool {
|
||||
self.0.is_low()
|
||||
}
|
||||
}
|
||||
|
||||
impl embedded_hal::digital::ErrorType for Input {
|
||||
type Error = Infallible;
|
||||
}
|
||||
|
||||
impl embedded_hal::digital::InputPin for Input {
|
||||
fn is_high(&mut self) -> Result<bool, Self::Error> {
|
||||
Ok(self.0.is_high())
|
||||
}
|
||||
|
||||
fn is_low(&mut self) -> Result<bool, Self::Error> {
|
||||
Ok(self.0.is_low())
|
||||
}
|
||||
}
|
||||
|
||||
/// IO peripheral pin.
|
||||
pub struct IoPeriphPin {
|
||||
pin: LowLevelGpio,
|
||||
mux_conf: MuxConf,
|
||||
}
|
||||
|
||||
impl IoPeriphPin {
|
||||
pub fn new(pin: impl MioPinMarker, mux_conf: MuxConf, pullup: Option<bool>) -> Self {
|
||||
let mut low_level = LowLevelGpio::new(PinOffset::Mio(pin.offset()));
|
||||
low_level.configure_as_io_periph_pin(mux_conf, pullup);
|
||||
Self {
|
||||
pin: low_level,
|
||||
mux_conf,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl IoPinProvider for IoPeriphPin {
|
||||
#[inline]
|
||||
fn mode(&self) -> PinMode {
|
||||
PinMode::MioIoPeriph(self.mux_conf)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn offset(&self) -> PinOffset {
|
||||
self.pin.offset()
|
||||
}
|
||||
}
|
||||
|
@ -6,16 +6,19 @@ use zynq7000::{
|
||||
};
|
||||
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
use crate::gpio::{
|
||||
use crate::gpio::mio::{
|
||||
Mio16, Mio17, Mio18, Mio19, Mio20, Mio21, Mio22, Mio23, Mio24, Mio25, Mio26, Mio27, Mio40,
|
||||
Mio41, Mio42, Mio43, Mio44, Mio45, Mio46, Mio47, Mio50, Mio51,
|
||||
};
|
||||
use crate::{
|
||||
enable_amba_peripheral_clock,
|
||||
gpio::{
|
||||
IoPeriph, IoPeriphPin, Mio10, Mio11, Mio12, Mio13, Mio14, Mio15, Mio28, Mio29, Mio30,
|
||||
Mio31, Mio32, Mio33, Mio34, Mio35, Mio36, Mio37, Mio38, Mio39, Mio48, Mio49, Mio52, Mio53,
|
||||
MioPin, MuxConf, PinMode,
|
||||
IoPeriphPin,
|
||||
mio::{
|
||||
Mio10, Mio11, Mio12, Mio13, Mio14, Mio15, Mio28, Mio29, Mio30, Mio31, Mio32, Mio33,
|
||||
Mio34, Mio35, Mio36, Mio37, Mio38, Mio39, Mio48, Mio49, Mio52, Mio53, MioPinMarker,
|
||||
MuxConf, Pin,
|
||||
},
|
||||
},
|
||||
slcr::Slcr,
|
||||
time::Hertz,
|
||||
@ -55,16 +58,31 @@ impl PsI2c for MmioI2c<'static> {
|
||||
}
|
||||
}
|
||||
|
||||
pub trait SdaPin: IoPeriphPin {
|
||||
pub trait SdaPin: MioPinMarker {
|
||||
const ID: I2cId;
|
||||
}
|
||||
|
||||
pub trait SckPin: IoPeriphPin {
|
||||
pub trait SckPin: MioPinMarker {
|
||||
const ID: I2cId;
|
||||
}
|
||||
|
||||
pub trait I2cPins {}
|
||||
|
||||
macro_rules! i2c_pin_impls {
|
||||
($Id: path, $SckMio:ident, $SdaMio:ident) => {
|
||||
impl SckPin for Pin<$SckMio> {
|
||||
const ID: I2cId = $Id;
|
||||
}
|
||||
|
||||
impl SdaPin for Pin<$SdaMio> {
|
||||
const ID: I2cId = $Id;
|
||||
}
|
||||
|
||||
impl I2cPins for (Pin<$SckMio>, Pin<$SdaMio>) {}
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
macro_rules! into_i2c {
|
||||
($($Mio:ident),+) => {
|
||||
$(
|
||||
@ -80,20 +98,6 @@ macro_rules! into_i2c {
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! i2c_pin_impls {
|
||||
($Id: path, $SckMio:ident, $SdaMio:ident) => {
|
||||
impl SckPin for MioPin<$SckMio, IoPeriph> {
|
||||
const ID: I2cId = $Id;
|
||||
}
|
||||
|
||||
impl SdaPin for MioPin<$SdaMio, IoPeriph> {
|
||||
const ID: I2cId = $Id;
|
||||
}
|
||||
|
||||
impl I2cPins for (MioPin<$SckMio, IoPeriph>, MioPin<$SdaMio, IoPeriph>) {}
|
||||
};
|
||||
}
|
||||
|
||||
into_i2c!(
|
||||
Mio10, Mio11, Mio14, Mio15, Mio30, Mio31, Mio34, Mio35, Mio38, Mio39, Mio12, Mio13, Mio28,
|
||||
Mio29, Mio32, Mio33, Mio36, Mio37, Mio48, Mio49, Mio52, Mio53
|
||||
@ -103,6 +107,7 @@ into_i2c!(
|
||||
Mio18, Mio19, Mio22, Mio23, Mio26, Mio27, Mio42, Mio43, Mio46, Mio47, Mio50, Mio51, Mio16,
|
||||
Mio17, Mio20, Mio21, Mio24, Mio25, Mio40, Mio41, Mio44, Mio45
|
||||
);
|
||||
*/
|
||||
|
||||
i2c_pin_impls!(I2cId::I2c0, Mio10, Mio11);
|
||||
i2c_pin_impls!(I2cId::I2c0, Mio14, Mio15);
|
||||
@ -318,9 +323,8 @@ impl I2c {
|
||||
if Sck::ID != Sda::ID {
|
||||
return Err(I2cConstructionError::PinInvalidForI2cId);
|
||||
}
|
||||
if i2c_pins.0.mux_conf() != I2C_MUX_CONF || i2c_pins.1.mux_conf() != I2C_MUX_CONF {
|
||||
return Err(I2cConstructionError::InvalidPinConf);
|
||||
}
|
||||
IoPeriphPin::new(i2c_pins.0, I2C_MUX_CONF, Some(true));
|
||||
IoPeriphPin::new(i2c_pins.1, I2C_MUX_CONF, Some(true));
|
||||
Ok(Self::new_generic(
|
||||
i2c.id().unwrap(),
|
||||
i2c.reg_block(),
|
||||
|
@ -198,6 +198,7 @@ pub fn disable_amba_peripheral_clock(select: PeripheralSelect) {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub(crate) mod sealed {
|
||||
pub trait Sealed {}
|
||||
}
|
||||
|
@ -3,12 +3,13 @@ use core::convert::Infallible;
|
||||
|
||||
use crate::clocks::Clocks;
|
||||
use crate::enable_amba_peripheral_clock;
|
||||
use crate::gpio::{
|
||||
IoPeriph, IoPeriphPin, Mio10, Mio11, Mio12, Mio13, Mio14, Mio15, Mio28, Mio29, Mio30, Mio31,
|
||||
Mio32, Mio33, Mio34, Mio35, Mio36, Mio37, Mio38, Mio39, MioPin, MuxConf,
|
||||
use crate::gpio::IoPeriphPin;
|
||||
use crate::gpio::mio::{
|
||||
Mio10, Mio11, Mio12, Mio13, Mio14, Mio15, Mio28, Mio29, Mio30, Mio31, Mio32, Mio33, Mio34,
|
||||
Mio35, Mio36, Mio37, Mio38, Mio39, MioPinMarker, MuxConf, Pin,
|
||||
};
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
use crate::gpio::{
|
||||
use crate::gpio::mio::{
|
||||
Mio16, Mio17, Mio18, Mio19, Mio20, Mio21, Mio22, Mio23, Mio24, Mio25, Mio26, Mio27, Mio40,
|
||||
Mio41, Mio42, Mio43, Mio44, Mio45, Mio46, Mio47, Mio48, Mio49, Mio50, Mio51,
|
||||
};
|
||||
@ -59,22 +60,22 @@ impl PsSpi for MmioSpi<'static> {
|
||||
}
|
||||
}
|
||||
|
||||
pub trait SckPin: IoPeriphPin {
|
||||
pub trait SckPin: MioPinMarker {
|
||||
const SPI: SpiId;
|
||||
const GROUP: usize;
|
||||
}
|
||||
|
||||
pub trait MosiPin: IoPeriphPin {
|
||||
pub trait MosiPin: MioPinMarker {
|
||||
const SPI: SpiId;
|
||||
const GROUP: usize;
|
||||
}
|
||||
|
||||
pub trait MisoPin: IoPeriphPin {
|
||||
pub trait MisoPin: MioPinMarker {
|
||||
const SPI: SpiId;
|
||||
const GROUP: usize;
|
||||
}
|
||||
|
||||
pub trait SsPin: IoPeriphPin {
|
||||
pub trait SsPin: MioPinMarker {
|
||||
const IDX: usize;
|
||||
const SPI: SpiId;
|
||||
const GROUP: usize;
|
||||
@ -82,15 +83,17 @@ pub trait SsPin: IoPeriphPin {
|
||||
|
||||
pub const SPI_MUX_CONF: MuxConf = MuxConf::new_with_l3(u3::new(0b101));
|
||||
|
||||
/*
|
||||
macro_rules! impl_into_spi {
|
||||
(($($Mio:ident),+)) => {
|
||||
$(
|
||||
impl<M: $crate::gpio::PinMode> MioPin<$Mio, M> {
|
||||
impl From<Pin<$Mio>> for IoPeriphPin {
|
||||
/// Convert the pin into SPI pins by configuring the pin routing via the
|
||||
/// MIO multiplexer bits. Also disables pull-ups for the pins.
|
||||
pub fn into_spi(self) -> MioPin<$Mio, IoPeriph> {
|
||||
self.into_io_periph(SPI_MUX_CONF, Some(false))
|
||||
fn from(pin: Pin<$Mio>) -> Self {
|
||||
IoPeriphPin::new(pin, SPI_MUX_CONF, Some(false))
|
||||
}
|
||||
|
||||
}
|
||||
)+
|
||||
};
|
||||
@ -106,66 +109,67 @@ impl_into_spi!((
|
||||
Mio28, Mio33, Mio29, Mio30, Mio31, Mio32, Mio12, Mio10, Mio11, Mio13, Mio14, Mio15, Mio36,
|
||||
Mio34, Mio35, Mio37, Mio38, Mio39
|
||||
));
|
||||
*/
|
||||
|
||||
// SPI0, choice 1
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl SckPin for MioPin<Mio16, IoPeriph> {
|
||||
impl SckPin for Pin<Mio16> {
|
||||
const SPI: SpiId = SpiId::Spi0;
|
||||
const GROUP: usize = 0;
|
||||
}
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl MosiPin for MioPin<Mio21, IoPeriph> {
|
||||
impl MosiPin for Pin<Mio21> {
|
||||
const SPI: SpiId = SpiId::Spi0;
|
||||
const GROUP: usize = 0;
|
||||
}
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl MisoPin for MioPin<Mio17, IoPeriph> {
|
||||
impl MisoPin for Pin<Mio17> {
|
||||
const SPI: SpiId = SpiId::Spi0;
|
||||
const GROUP: usize = 0;
|
||||
}
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl SsPin for MioPin<Mio18, IoPeriph> {
|
||||
impl SsPin for Pin<Mio18> {
|
||||
const SPI: SpiId = SpiId::Spi0;
|
||||
const GROUP: usize = 0;
|
||||
const IDX: usize = 0;
|
||||
}
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl SsPin for MioPin<Mio19, IoPeriph> {
|
||||
impl SsPin for Pin<Mio19> {
|
||||
const SPI: SpiId = SpiId::Spi0;
|
||||
const GROUP: usize = 0;
|
||||
const IDX: usize = 1;
|
||||
}
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl SsPin for MioPin<Mio20, IoPeriph> {
|
||||
impl SsPin for Pin<Mio20> {
|
||||
const SPI: SpiId = SpiId::Spi0;
|
||||
const GROUP: usize = 0;
|
||||
const IDX: usize = 2;
|
||||
}
|
||||
|
||||
// SPI0, choice 2
|
||||
impl SckPin for MioPin<Mio28, IoPeriph> {
|
||||
impl SckPin for Pin<Mio28> {
|
||||
const SPI: SpiId = SpiId::Spi0;
|
||||
const GROUP: usize = 1;
|
||||
}
|
||||
impl MosiPin for MioPin<Mio33, IoPeriph> {
|
||||
impl MosiPin for Pin<Mio33> {
|
||||
const SPI: SpiId = SpiId::Spi0;
|
||||
const GROUP: usize = 1;
|
||||
}
|
||||
impl MisoPin for MioPin<Mio29, IoPeriph> {
|
||||
impl MisoPin for Pin<Mio29> {
|
||||
const SPI: SpiId = SpiId::Spi0;
|
||||
const GROUP: usize = 1;
|
||||
}
|
||||
impl SsPin for MioPin<Mio30, IoPeriph> {
|
||||
impl SsPin for Pin<Mio30> {
|
||||
const SPI: SpiId = SpiId::Spi0;
|
||||
const GROUP: usize = 1;
|
||||
const IDX: usize = 0;
|
||||
}
|
||||
impl SsPin for MioPin<Mio31, IoPeriph> {
|
||||
impl SsPin for Pin<Mio31> {
|
||||
const SPI: SpiId = SpiId::Spi0;
|
||||
const GROUP: usize = 1;
|
||||
const IDX: usize = 1;
|
||||
}
|
||||
impl SsPin for MioPin<Mio32, IoPeriph> {
|
||||
impl SsPin for Pin<Mio32> {
|
||||
const SPI: SpiId = SpiId::Spi0;
|
||||
const GROUP: usize = 1;
|
||||
const IDX: usize = 2;
|
||||
@ -173,63 +177,63 @@ impl SsPin for MioPin<Mio32, IoPeriph> {
|
||||
|
||||
// SPI0, choice 3
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl SckPin for MioPin<Mio40, IoPeriph> {
|
||||
impl SckPin for Pin<Mio40> {
|
||||
const SPI: SpiId = SpiId::Spi0;
|
||||
const GROUP: usize = 2;
|
||||
}
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl MosiPin for MioPin<Mio45, IoPeriph> {
|
||||
impl MosiPin for Pin<Mio45> {
|
||||
const SPI: SpiId = SpiId::Spi0;
|
||||
const GROUP: usize = 2;
|
||||
}
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl MisoPin for MioPin<Mio41, IoPeriph> {
|
||||
impl MisoPin for Pin<Mio41> {
|
||||
const SPI: SpiId = SpiId::Spi0;
|
||||
const GROUP: usize = 2;
|
||||
}
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl SsPin for MioPin<Mio42, IoPeriph> {
|
||||
impl SsPin for Pin<Mio42> {
|
||||
const SPI: SpiId = SpiId::Spi0;
|
||||
const GROUP: usize = 2;
|
||||
const IDX: usize = 0;
|
||||
}
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl SsPin for MioPin<Mio43, IoPeriph> {
|
||||
impl SsPin for Pin<Mio43> {
|
||||
const SPI: SpiId = SpiId::Spi0;
|
||||
const GROUP: usize = 2;
|
||||
const IDX: usize = 1;
|
||||
}
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl SsPin for MioPin<Mio44, IoPeriph> {
|
||||
impl SsPin for Pin<Mio44> {
|
||||
const SPI: SpiId = SpiId::Spi0;
|
||||
const GROUP: usize = 2;
|
||||
const IDX: usize = 2;
|
||||
}
|
||||
|
||||
// SPI1, choice 1
|
||||
impl SckPin for MioPin<Mio12, IoPeriph> {
|
||||
impl SckPin for Pin<Mio12> {
|
||||
const SPI: SpiId = SpiId::Spi1;
|
||||
const GROUP: usize = 0;
|
||||
}
|
||||
impl MosiPin for MioPin<Mio10, IoPeriph> {
|
||||
impl MosiPin for Pin<Mio10> {
|
||||
const SPI: SpiId = SpiId::Spi1;
|
||||
const GROUP: usize = 0;
|
||||
}
|
||||
impl MisoPin for MioPin<Mio11, IoPeriph> {
|
||||
impl MisoPin for Pin<Mio11> {
|
||||
const SPI: SpiId = SpiId::Spi1;
|
||||
const GROUP: usize = 0;
|
||||
}
|
||||
impl SsPin for MioPin<Mio13, IoPeriph> {
|
||||
impl SsPin for Pin<Mio13> {
|
||||
const SPI: SpiId = SpiId::Spi1;
|
||||
const GROUP: usize = 0;
|
||||
const IDX: usize = 0;
|
||||
}
|
||||
impl SsPin for MioPin<Mio14, IoPeriph> {
|
||||
impl SsPin for Pin<Mio14> {
|
||||
const SPI: SpiId = SpiId::Spi1;
|
||||
const GROUP: usize = 0;
|
||||
const IDX: usize = 1;
|
||||
}
|
||||
impl SsPin for MioPin<Mio15, IoPeriph> {
|
||||
impl SsPin for Pin<Mio15> {
|
||||
const SPI: SpiId = SpiId::Spi1;
|
||||
const GROUP: usize = 0;
|
||||
const IDX: usize = 2;
|
||||
@ -237,63 +241,63 @@ impl SsPin for MioPin<Mio15, IoPeriph> {
|
||||
|
||||
// SPI1, choice 2
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl SckPin for MioPin<Mio24, IoPeriph> {
|
||||
impl SckPin for Pin<Mio24> {
|
||||
const SPI: SpiId = SpiId::Spi1;
|
||||
const GROUP: usize = 1;
|
||||
}
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl MosiPin for MioPin<Mio22, IoPeriph> {
|
||||
impl MosiPin for Pin<Mio22> {
|
||||
const SPI: SpiId = SpiId::Spi1;
|
||||
const GROUP: usize = 1;
|
||||
}
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl MisoPin for MioPin<Mio23, IoPeriph> {
|
||||
impl MisoPin for Pin<Mio23> {
|
||||
const SPI: SpiId = SpiId::Spi1;
|
||||
const GROUP: usize = 1;
|
||||
}
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl SsPin for MioPin<Mio25, IoPeriph> {
|
||||
impl SsPin for Pin<Mio25> {
|
||||
const SPI: SpiId = SpiId::Spi1;
|
||||
const GROUP: usize = 1;
|
||||
const IDX: usize = 0;
|
||||
}
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl SsPin for MioPin<Mio26, IoPeriph> {
|
||||
impl SsPin for Pin<Mio26> {
|
||||
const SPI: SpiId = SpiId::Spi1;
|
||||
const GROUP: usize = 1;
|
||||
const IDX: usize = 1;
|
||||
}
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl SsPin for MioPin<Mio27, IoPeriph> {
|
||||
impl SsPin for Pin<Mio27> {
|
||||
const SPI: SpiId = SpiId::Spi1;
|
||||
const GROUP: usize = 1;
|
||||
const IDX: usize = 2;
|
||||
}
|
||||
|
||||
// SPI1, choice 2
|
||||
impl SckPin for MioPin<Mio36, IoPeriph> {
|
||||
impl SckPin for Pin<Mio36> {
|
||||
const SPI: SpiId = SpiId::Spi1;
|
||||
const GROUP: usize = 2;
|
||||
}
|
||||
impl MosiPin for MioPin<Mio34, IoPeriph> {
|
||||
impl MosiPin for Pin<Mio34> {
|
||||
const SPI: SpiId = SpiId::Spi1;
|
||||
const GROUP: usize = 2;
|
||||
}
|
||||
impl MisoPin for MioPin<Mio35, IoPeriph> {
|
||||
impl MisoPin for Pin<Mio35> {
|
||||
const SPI: SpiId = SpiId::Spi1;
|
||||
const GROUP: usize = 2;
|
||||
}
|
||||
impl SsPin for MioPin<Mio37, IoPeriph> {
|
||||
impl SsPin for Pin<Mio37> {
|
||||
const SPI: SpiId = SpiId::Spi1;
|
||||
const GROUP: usize = 2;
|
||||
const IDX: usize = 0;
|
||||
}
|
||||
impl SsPin for MioPin<Mio38, IoPeriph> {
|
||||
impl SsPin for Pin<Mio38> {
|
||||
const SPI: SpiId = SpiId::Spi1;
|
||||
const GROUP: usize = 2;
|
||||
const IDX: usize = 1;
|
||||
}
|
||||
impl SsPin for MioPin<Mio39, IoPeriph> {
|
||||
impl SsPin for Pin<Mio39> {
|
||||
const SPI: SpiId = SpiId::Spi1;
|
||||
const GROUP: usize = 2;
|
||||
const IDX: usize = 2;
|
||||
@ -301,34 +305,34 @@ impl SsPin for MioPin<Mio39, IoPeriph> {
|
||||
|
||||
// SPI1, choice 3
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl SckPin for MioPin<Mio48, IoPeriph> {
|
||||
impl SckPin for Pin<Mio48> {
|
||||
const SPI: SpiId = SpiId::Spi1;
|
||||
const GROUP: usize = 3;
|
||||
}
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl MosiPin for MioPin<Mio46, IoPeriph> {
|
||||
impl MosiPin for Pin<Mio46> {
|
||||
const SPI: SpiId = SpiId::Spi1;
|
||||
const GROUP: usize = 3;
|
||||
}
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl MisoPin for MioPin<Mio47, IoPeriph> {
|
||||
impl MisoPin for Pin<Mio47> {
|
||||
const SPI: SpiId = SpiId::Spi1;
|
||||
const GROUP: usize = 3;
|
||||
}
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl SsPin for MioPin<Mio49, IoPeriph> {
|
||||
impl SsPin for Pin<Mio49> {
|
||||
const SPI: SpiId = SpiId::Spi1;
|
||||
const GROUP: usize = 3;
|
||||
const IDX: usize = 0;
|
||||
}
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl SsPin for MioPin<Mio50, IoPeriph> {
|
||||
impl SsPin for Pin<Mio50> {
|
||||
const SPI: SpiId = SpiId::Spi1;
|
||||
const GROUP: usize = 3;
|
||||
const IDX: usize = 1;
|
||||
}
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl SsPin for MioPin<Mio51, IoPeriph> {
|
||||
impl SsPin for Pin<Mio51> {
|
||||
const SPI: SpiId = SpiId::Spi1;
|
||||
const GROUP: usize = 3;
|
||||
const IDX: usize = 2;
|
||||
@ -555,8 +559,7 @@ impl SpiLowLevel {
|
||||
|
||||
#[inline(always)]
|
||||
pub fn write_fifo_unchecked(&mut self, data: u8) {
|
||||
self.regs
|
||||
.write_txd(FifoWrite::new(data));
|
||||
self.regs.write_txd(FifoWrite::new(data));
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
@ -706,12 +709,9 @@ impl Spi {
|
||||
if Sck::SPI != spi_id || Mosi::SPI != spi_id || Miso::SPI != spi_id {
|
||||
return Err(SpiConstructionError::PinInvalidForSpiId);
|
||||
}
|
||||
if spi_pins.0.mux_conf() != SPI_MUX_CONF
|
||||
|| spi_pins.0.mux_conf() != spi_pins.2.mux_conf()
|
||||
|| spi_pins.1.mux_conf() != spi_pins.2.mux_conf()
|
||||
{
|
||||
return Err(SpiConstructionError::InvalidPinConf);
|
||||
}
|
||||
IoPeriphPin::new(spi_pins.0, SPI_MUX_CONF, Some(false));
|
||||
IoPeriphPin::new(spi_pins.1, SPI_MUX_CONF, Some(false));
|
||||
IoPeriphPin::new(spi_pins.2, SPI_MUX_CONF, Some(false));
|
||||
Ok(Self::new_generic_unchecked(
|
||||
spi_id,
|
||||
spi.reg_block(),
|
||||
@ -738,13 +738,10 @@ impl Spi {
|
||||
if Sck::SPI != spi_id || Mosi::SPI != spi_id || Miso::SPI != spi_id || Ss::SPI != spi_id {
|
||||
return Err(SpiConstructionError::PinInvalidForSpiId);
|
||||
}
|
||||
if spi_pins.0.mux_conf() != SPI_MUX_CONF
|
||||
|| spi_pins.0.mux_conf() != spi_pins.2.mux_conf()
|
||||
|| spi_pins.1.mux_conf() != spi_pins.2.mux_conf()
|
||||
|| ss_pin.mux_conf() != spi_pins.0.mux_conf()
|
||||
{
|
||||
return Err(SpiConstructionError::InvalidPinConf);
|
||||
}
|
||||
IoPeriphPin::new(spi_pins.0, SPI_MUX_CONF, Some(false));
|
||||
IoPeriphPin::new(spi_pins.1, SPI_MUX_CONF, Some(false));
|
||||
IoPeriphPin::new(spi_pins.2, SPI_MUX_CONF, Some(false));
|
||||
IoPeriphPin::new(ss_pin, SPI_MUX_CONF, Some(false));
|
||||
Ok(Self::new_generic_unchecked(
|
||||
spi_id,
|
||||
spi.reg_block(),
|
||||
@ -780,14 +777,11 @@ impl Spi {
|
||||
{
|
||||
return Err(SpiConstructionError::PinInvalidForSpiId);
|
||||
}
|
||||
if spi_pins.0.mux_conf() != SPI_MUX_CONF
|
||||
|| spi_pins.0.mux_conf() != spi_pins.2.mux_conf()
|
||||
|| spi_pins.1.mux_conf() != spi_pins.2.mux_conf()
|
||||
|| ss_pins.0.mux_conf() != spi_pins.0.mux_conf()
|
||||
|| ss_pins.1.mux_conf() != spi_pins.0.mux_conf()
|
||||
{
|
||||
return Err(SpiConstructionError::InvalidPinConf);
|
||||
}
|
||||
IoPeriphPin::new(spi_pins.0, SPI_MUX_CONF, Some(false));
|
||||
IoPeriphPin::new(spi_pins.1, SPI_MUX_CONF, Some(false));
|
||||
IoPeriphPin::new(spi_pins.2, SPI_MUX_CONF, Some(false));
|
||||
IoPeriphPin::new(ss_pins.0, SPI_MUX_CONF, Some(false));
|
||||
IoPeriphPin::new(ss_pins.1, SPI_MUX_CONF, Some(false));
|
||||
Ok(Self::new_generic_unchecked(
|
||||
spi_id,
|
||||
spi.reg_block(),
|
||||
@ -832,15 +826,12 @@ impl Spi {
|
||||
{
|
||||
return Err(SpiConstructionError::PinInvalidForSpiId);
|
||||
}
|
||||
if spi_pins.0.mux_conf() != SPI_MUX_CONF
|
||||
|| spi_pins.0.mux_conf() != spi_pins.2.mux_conf()
|
||||
|| spi_pins.1.mux_conf() != spi_pins.2.mux_conf()
|
||||
|| ss_pins.0.mux_conf() != spi_pins.0.mux_conf()
|
||||
|| ss_pins.1.mux_conf() != spi_pins.0.mux_conf()
|
||||
|| ss_pins.2.mux_conf() != spi_pins.2.mux_conf()
|
||||
{
|
||||
return Err(SpiConstructionError::InvalidPinConf);
|
||||
}
|
||||
IoPeriphPin::new(spi_pins.0, SPI_MUX_CONF, Some(false));
|
||||
IoPeriphPin::new(spi_pins.1, SPI_MUX_CONF, Some(false));
|
||||
IoPeriphPin::new(spi_pins.2, SPI_MUX_CONF, Some(false));
|
||||
IoPeriphPin::new(ss_pins.0, SPI_MUX_CONF, Some(false));
|
||||
IoPeriphPin::new(ss_pins.1, SPI_MUX_CONF, Some(false));
|
||||
IoPeriphPin::new(ss_pins.2, SPI_MUX_CONF, Some(false));
|
||||
Ok(Self::new_generic_unchecked(
|
||||
spi_id,
|
||||
spi.reg_block(),
|
||||
|
@ -8,10 +8,13 @@ use arbitrary_int::{Number, u3, u4};
|
||||
use zynq7000::ttc::{MmioTtc, TTC_0_BASE_ADDR, TTC_1_BASE_ADDR};
|
||||
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
use crate::gpio::{Mio16, Mio17, Mio18, Mio19, Mio40, Mio41, Mio42, Mio43};
|
||||
use crate::gpio::mio::{Mio16, Mio17, Mio18, Mio19, Mio40, Mio41, Mio42, Mio43};
|
||||
use crate::{
|
||||
clocks::ArmClocks,
|
||||
gpio::{IoPeriph, IoPeriphPin, Mio28, Mio29, Mio30, Mio31, MioPin, MuxConf, PinMode},
|
||||
gpio::{
|
||||
IoPeriphPin,
|
||||
mio::{Mio28, Mio29, Mio30, Mio31, MioPinMarker, MuxConf, Pin},
|
||||
},
|
||||
time::Hertz,
|
||||
};
|
||||
|
||||
@ -54,31 +57,65 @@ impl PsTtc for MmioTtc<'static> {
|
||||
|
||||
pub const TTC_MUX_CONF: MuxConf = MuxConf::new_with_l3(u3::new(0b110));
|
||||
|
||||
pub trait ClockInPin: IoPeriphPin {
|
||||
pub trait ClockInPin: MioPinMarker {
|
||||
const ID: TtcId;
|
||||
}
|
||||
|
||||
pub trait WaveOutPin: IoPeriphPin {
|
||||
pub trait WaveOutPin: MioPinMarker {
|
||||
const ID: TtcId;
|
||||
}
|
||||
|
||||
macro_rules! into_ttc {
|
||||
($($Mio:ident),+) => {
|
||||
$(
|
||||
impl <M: PinMode> MioPin<$Mio, M> {
|
||||
/// Convert the pin into a TTC pin by configuring the pin routing via the
|
||||
/// MIO multiplexer bits.
|
||||
pub fn into_ttck(self) -> MioPin<$Mio, IoPeriph> {
|
||||
self.into_io_periph(TTC_MUX_CONF, None)
|
||||
}
|
||||
}
|
||||
)+
|
||||
};
|
||||
}
|
||||
// TTC0 pin trait implementations.
|
||||
|
||||
impl ClockInPin for Pin<Mio19> {
|
||||
const ID: TtcId = TtcId::Ttc0;
|
||||
}
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
into_ttc!(Mio16, Mio17, Mio18, Mio19, Mio40, Mio41, Mio42, Mio43);
|
||||
into_ttc!(Mio28, Mio29, Mio30, Mio31);
|
||||
impl ClockInPin for Pin<Mio31> {
|
||||
const ID: TtcId = TtcId::Ttc0;
|
||||
}
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl ClockInPin for Pin<Mio43> {
|
||||
const ID: TtcId = TtcId::Ttc0;
|
||||
}
|
||||
|
||||
impl WaveOutPin for Pin<Mio18> {
|
||||
const ID: TtcId = TtcId::Ttc0;
|
||||
}
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl WaveOutPin for Pin<Mio30> {
|
||||
const ID: TtcId = TtcId::Ttc0;
|
||||
}
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl WaveOutPin for Pin<Mio42> {
|
||||
const ID: TtcId = TtcId::Ttc0;
|
||||
}
|
||||
|
||||
// TTC1 pin trait implementations.
|
||||
|
||||
impl ClockInPin for Pin<Mio17> {
|
||||
const ID: TtcId = TtcId::Ttc1;
|
||||
}
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl ClockInPin for Pin<Mio29> {
|
||||
const ID: TtcId = TtcId::Ttc1;
|
||||
}
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl ClockInPin for Pin<Mio41> {
|
||||
const ID: TtcId = TtcId::Ttc1;
|
||||
}
|
||||
|
||||
impl WaveOutPin for Pin<Mio16> {
|
||||
const ID: TtcId = TtcId::Ttc1;
|
||||
}
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl WaveOutPin for Pin<Mio28> {
|
||||
const ID: TtcId = TtcId::Ttc1;
|
||||
}
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl WaveOutPin for Pin<Mio40> {
|
||||
const ID: TtcId = TtcId::Ttc1;
|
||||
}
|
||||
|
||||
pub struct Ttc {
|
||||
pub ch0: TtcChannel,
|
||||
@ -187,9 +224,7 @@ impl Pwm {
|
||||
freq: Hertz,
|
||||
wave_out: impl WaveOutPin,
|
||||
) -> Result<Self, TtcConstructionError> {
|
||||
if wave_out.mux_conf() != TTC_MUX_CONF {
|
||||
return Err(InvalidTtcPinConfigError(wave_out.mux_conf()).into());
|
||||
}
|
||||
IoPeriphPin::new(wave_out, TTC_MUX_CONF, None);
|
||||
Ok(Self::new_with_cpu_clk(channel, arm_clocks, freq)?)
|
||||
}
|
||||
|
||||
|
@ -16,15 +16,18 @@ use zynq7000::{
|
||||
use crate::{
|
||||
enable_amba_peripheral_clock,
|
||||
gpio::{
|
||||
IoPeriph, IoPeriphPin, Mio8, Mio9, Mio10, Mio11, Mio12, Mio13, Mio14, Mio15, Mio28, Mio29,
|
||||
Mio30, Mio31, Mio32, Mio33, Mio34, Mio35, Mio36, Mio37, Mio38, Mio39, Mio48, Mio49, Mio52,
|
||||
Mio53, MioPin, MuxConf, PinMode,
|
||||
IoPeriphPin,
|
||||
mio::{
|
||||
Mio8, Mio9, Mio10, Mio11, Mio12, Mio13, Mio14, Mio15, Mio28, Mio29, Mio30, Mio31,
|
||||
Mio32, Mio33, Mio34, Mio35, Mio36, Mio37, Mio38, Mio39, Mio48, Mio49, Mio52, Mio53,
|
||||
MioPinMarker, MuxConf, Pin,
|
||||
},
|
||||
},
|
||||
slcr::Slcr,
|
||||
};
|
||||
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
use crate::gpio::{
|
||||
use crate::gpio::mio::{
|
||||
Mio16, Mio17, Mio18, Mio19, Mio20, Mio21, Mio22, Mio23, Mio24, Mio25, Mio26, Mio27, Mio40,
|
||||
Mio41, Mio42, Mio43, Mio44, Mio45, Mio46, Mio47, Mio50, Mio51,
|
||||
};
|
||||
@ -86,10 +89,10 @@ impl UartId {
|
||||
}
|
||||
}
|
||||
|
||||
pub trait RxPin {
|
||||
pub trait RxPin: MioPinMarker {
|
||||
const UART_IDX: UartId;
|
||||
}
|
||||
pub trait TxPin {
|
||||
pub trait TxPin: MioPinMarker {
|
||||
const UART_IDX: UartId;
|
||||
}
|
||||
|
||||
@ -103,27 +106,27 @@ macro_rules! pin_pairs {
|
||||
($UartPeriph:path, ($( [$(#[$meta:meta], )? $TxMio:ident, $RxMio:ident] ),+ $(,)? )) => {
|
||||
$(
|
||||
$( #[$meta] )?
|
||||
impl TxPin for MioPin<$TxMio, IoPeriph> {
|
||||
impl TxPin for Pin<$TxMio> {
|
||||
const UART_IDX: UartId = $UartPeriph;
|
||||
}
|
||||
|
||||
|
||||
$( #[$meta] )?
|
||||
impl RxPin for MioPin<$RxMio, IoPeriph> {
|
||||
impl RxPin for Pin<$RxMio> {
|
||||
const UART_IDX: UartId = $UartPeriph;
|
||||
}
|
||||
|
||||
impl UartPins for (MioPin<$TxMio, IoPeriph>, MioPin<$RxMio, IoPeriph>) {}
|
||||
impl UartPins for (Pin<$TxMio>, Pin<$RxMio>) {}
|
||||
)+
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
macro_rules! impl_into_uart {
|
||||
(($($Mio:ident),+)) => {
|
||||
$(
|
||||
impl<M: PinMode> MioPin<$Mio, M> {
|
||||
pub fn into_uart(self) -> MioPin<$Mio, IoPeriph> {
|
||||
self.into_io_periph(UART_MUX_CONF, None)
|
||||
impl From<Pin<$Mio>> for IoPeriphPin {
|
||||
fn from(pin: Pin<$Mio>) -> Self {
|
||||
IoPeriphPin::new(pin, UART_MUX_CONF, None)
|
||||
}
|
||||
}
|
||||
)+
|
||||
@ -140,6 +143,7 @@ impl_into_uart!((
|
||||
Mio19, Mio18, Mio23, Mio22, Mio43, Mio42, Mio47, Mio46, Mio51, Mio50, Mio16, Mio17, Mio20,
|
||||
Mio21, Mio24, Mio25, Mio40, Mio41, Mio44, Mio45
|
||||
));
|
||||
*/
|
||||
|
||||
pin_pairs!(
|
||||
UartId::Uart0,
|
||||
@ -453,7 +457,7 @@ impl Uart {
|
||||
}
|
||||
|
||||
/// This is the constructor to use the PS UART with MIO pins.
|
||||
pub fn new_with_mio<TxPinI: TxPin + IoPeriphPin, RxPinI: RxPin + IoPeriphPin>(
|
||||
pub fn new_with_mio<TxPinI: TxPin, RxPinI: RxPin>(
|
||||
uart: impl PsUart,
|
||||
cfg: UartConfig,
|
||||
pins: (TxPinI, RxPinI),
|
||||
@ -468,12 +472,8 @@ impl Uart {
|
||||
if id.unwrap() != TxPinI::UART_IDX || id.unwrap() != RxPinI::UART_IDX {
|
||||
return Err(UartConstructionError::IdxMissmatch);
|
||||
}
|
||||
if pins.0.mux_conf() != UART_MUX_CONF {
|
||||
return Err(UartConstructionError::InvalidMuxConf(pins.0.mux_conf()));
|
||||
}
|
||||
if pins.1.mux_conf() != UART_MUX_CONF {
|
||||
return Err(UartConstructionError::InvalidMuxConf(pins.1.mux_conf()));
|
||||
}
|
||||
IoPeriphPin::new(pins.0, UART_MUX_CONF, None);
|
||||
IoPeriphPin::new(pins.1, UART_MUX_CONF, None);
|
||||
Ok(Self::new_generic_unchecked(
|
||||
uart.reg_block(),
|
||||
id.unwrap(),
|
||||
|
@ -11,8 +11,8 @@ keywords = ["no-std", "arm", "cortex-a", "amd", "zynq7000"]
|
||||
categories = ["embedded", "no-std", "hardware-support"]
|
||||
|
||||
[dependencies]
|
||||
cortex-a-rt = { path = "/home/rmueller/Rust/cortex-ar/cortex-a-rt", optional = true, features = ["vfp-dp"] }
|
||||
cortex-ar = { path = "/home/rmueller/Rust/cortex-ar/cortex-ar" }
|
||||
cortex-a-rt = { git = "https://github.com/rust-embedded/cortex-ar", branch = "main", optional = true, features = ["vfp-dp"] }
|
||||
cortex-ar = { git = "https://github.com/rust-embedded/cortex-ar", branch = "main", features = ["critical-section-single-core"] }
|
||||
|
||||
[features]
|
||||
default = ["rt"]
|
||||
|
@ -1,5 +1,5 @@
|
||||
//! SPI register module.
|
||||
use arbitrary_int::{u4, Number};
|
||||
use arbitrary_int::{Number, u4};
|
||||
|
||||
pub const SPI_0_BASE_ADDR: usize = 0xE000_6000;
|
||||
pub const SPI_1_BASE_ADDR: usize = 0xE000_7000;
|
||||
@ -140,7 +140,7 @@ impl FifoWrite {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn write(&mut self, value:u8) {
|
||||
pub fn write(&mut self, value: u8) {
|
||||
self.0 = value.into();
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user