1d needs to be builded again from scratch
This commit is contained in:
8
semestralka_1_2hwuart_internal/Cargo.lock
generated
8
semestralka_1_2hwuart_internal/Cargo.lock
generated
@@ -1064,17 +1064,17 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "stm32-fmc"
|
name = "stm32-fmc"
|
||||||
version = "0.4.0"
|
version = "0.3.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "72692594faa67f052e5e06dd34460951c21e83bc55de4feb8d2666e2f15480a2"
|
checksum = "c7f0639399e2307c2446c54d91d4f1596343a1e1d5cab605b9cce11d0ab3858c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"embedded-hal 1.0.0",
|
"embedded-hal 0.2.7",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "stm32-metapac"
|
name = "stm32-metapac"
|
||||||
version = "18.0.0"
|
version = "18.0.0"
|
||||||
source = "git+https://github.com/embassy-rs/stm32-data-generated?tag=stm32-data-22374e3344a2c9150b9b3d4da45c03f398fdc54e#31546499ddabe97044beae13ca8b535575b52a56"
|
source = "git+https://github.com/embassy-rs/stm32-data-generated?tag=stm32-data-b9f6b0c542d85ee695d71c35ced195e0cef51ac0#9b8fb67703361e2237b6c1ec4f1ee5949223d412"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cortex-m",
|
"cortex-m",
|
||||||
"cortex-m-rt",
|
"cortex-m-rt",
|
||||||
|
|||||||
@@ -111,9 +111,7 @@ async fn main(spawner: Spawner) {
|
|||||||
|
|
||||||
let mut last_state: u8 = 0;
|
let mut last_state: u8 = 0;
|
||||||
loop {
|
loop {
|
||||||
tx_pin.set_high();
|
// info!("tick start");
|
||||||
Timer::after(Duration::from_millis(10)).await;
|
|
||||||
info!("tick start");
|
|
||||||
// Timer::after(Duration::from_millis(100)).await;
|
// Timer::after(Duration::from_millis(100)).await;
|
||||||
// info!("tick end");
|
// info!("tick end");
|
||||||
|
|
||||||
@@ -125,24 +123,6 @@ async fn main(spawner: Spawner) {
|
|||||||
// }
|
// }
|
||||||
// yield_now().await;
|
// yield_now().await;
|
||||||
|
|
||||||
let bit = rx_pin.is_high();
|
|
||||||
// info!("Rx_pin read (high): {}", bit);
|
|
||||||
if bit as u8 != last_state {
|
|
||||||
info!(
|
|
||||||
"SW RX -> PD6 changed, new state = {}",
|
|
||||||
if bit { "HIGH" } else { "LOW" }
|
|
||||||
);
|
|
||||||
last_state = bit as u8;
|
|
||||||
continue;
|
|
||||||
yield_now().await;
|
|
||||||
}
|
|
||||||
Timer::after(Duration::from_millis(1)).await;
|
|
||||||
|
|
||||||
// ZNOVA TO ISTE ALE LOW
|
|
||||||
tx_pin.set_low();
|
|
||||||
Timer::after(Duration::from_millis(1)).await;
|
|
||||||
let low_state = rx_pin.is_high();
|
|
||||||
defmt::info!("Rx_pin (read): {}", low_state);
|
|
||||||
|
|
||||||
yield_now().await;
|
yield_now().await;
|
||||||
}
|
}
|
||||||
@@ -174,7 +154,7 @@ pub async fn bridge_usart2_rx_to_usart1_tx(
|
|||||||
let n = usart2_rx.read(&mut buf).await;
|
let n = usart2_rx.read(&mut buf).await;
|
||||||
if n > 0 {
|
if n > 0 {
|
||||||
let _ = usart1_tx.write(&buf[..n]).await;
|
let _ = usart1_tx.write(&buf[..n]).await;
|
||||||
info!("bridge: USART2 -> USART1 sent {} bytes", n);
|
// info!("bridge: USART2 -> USART1 sent {} bytes", n);
|
||||||
}
|
}
|
||||||
yield_now().await;
|
yield_now().await;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,14 +4,17 @@
|
|||||||
|
|
||||||
use defmt::*;
|
use defmt::*;
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
|
use embassy_time::Instant;
|
||||||
use embassy_stm32::dma::Request;
|
use embassy_stm32::dma::Request;
|
||||||
use embassy_stm32::gpio::{Input, Pull};
|
use embassy_stm32::gpio::{Input, Output, Level, Pull, Speed};
|
||||||
use dma_gpio::software_uart::{
|
use dma_gpio::software_uart::{
|
||||||
dma_timer::{init_tim6_for_uart, init_tim7_for_uart},
|
dma_timer::{init_tim6_for_uart, init_tim7_for_uart},
|
||||||
|
gpio_dma_uart_rx::rx_dma_task,
|
||||||
debug::dump_tim6_regs,
|
debug::dump_tim6_regs,
|
||||||
};
|
};
|
||||||
use dma_gpio::config::{BAUD, RX_OVERSAMPLE, TX_OVERSAMPLE};
|
use dma_gpio::config::{BAUD, RX_OVERSAMPLE, TX_OVERSAMPLE};
|
||||||
use dma_gpio::config::{TX_RING_BYTES, RX_RING_BYTES};
|
use dma_gpio::config::{TX_RING_BYTES, RX_RING_BYTES};
|
||||||
|
use dma_gpio::software_uart::gpio_dma_uart_tx::tx_dma_task;
|
||||||
use static_cell::StaticCell;
|
use static_cell::StaticCell;
|
||||||
use embassy_futures::yield_now;
|
use embassy_futures::yield_now;
|
||||||
use dma_gpio::hw_uart_pc::usart1;
|
use dma_gpio::hw_uart_pc::usart1;
|
||||||
@@ -19,22 +22,14 @@ use dma_gpio::hw_uart_pc::driver::uart_task;
|
|||||||
use embassy_stm32::usart::{BufferedUart, Config, BufferedInterruptHandler};
|
use embassy_stm32::usart::{BufferedUart, Config, BufferedInterruptHandler};
|
||||||
use embassy_stm32::peripherals;
|
use embassy_stm32::peripherals;
|
||||||
use embassy_stm32::bind_interrupts;
|
use embassy_stm32::bind_interrupts;
|
||||||
use dma_gpio::config::{PIPE_HW_TX, PIPE_HW_RX};
|
use dma_gpio::config::{PIPE_HW_TX, PIPE_HW_RX, PIPE_SW_TX, PIPE_SW_RX};
|
||||||
use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, pipe::Pipe};
|
use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, pipe::Pipe};
|
||||||
use dma_gpio::hw_uart_internal::usart2;
|
use dma_gpio::hw_uart_internal::usart2;
|
||||||
use dma_gpio::hw_uart_internal::driver::uart_task as uart_task_internal;
|
use dma_gpio::hw_uart_internal::driver::uart_task as uart_task_internal;
|
||||||
use dma_gpio::config::{PIPE_INT_TX, PIPE_INT_RX};
|
use dma_gpio::config::{PIPE_INT_TX, PIPE_INT_RX};
|
||||||
use embassy_stm32::pac;
|
|
||||||
use embassy_stm32::interrupt;
|
|
||||||
use embassy_time::{Duration, Timer};
|
use embassy_time::{Duration, Timer};
|
||||||
use embassy_sync::channel::Channel;
|
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
use cortex_m::interrupt::Mutex;
|
|
||||||
use core::cell::RefCell;
|
|
||||||
|
|
||||||
static RX_PIN_GLOBAL: Mutex<RefCell<Option<&'static mut Input<'static>>>> = Mutex::new(RefCell::new(None));
|
|
||||||
|
|
||||||
bind_interrupts!(struct Irqs {
|
bind_interrupts!(struct Irqs {
|
||||||
USART1 => BufferedInterruptHandler<peripherals::USART1>;
|
USART1 => BufferedInterruptHandler<peripherals::USART1>;
|
||||||
});
|
});
|
||||||
@@ -46,13 +41,14 @@ bind_interrupts!(struct Irqs2 {
|
|||||||
pub const TIM6_UP_REQ: Request = 4;
|
pub const TIM6_UP_REQ: Request = 4;
|
||||||
static SW_TX_RING: StaticCell<[u32; TX_RING_BYTES]> = StaticCell::new();
|
static SW_TX_RING: StaticCell<[u32; TX_RING_BYTES]> = StaticCell::new();
|
||||||
static SW_RX_RING: StaticCell<[u8; RX_RING_BYTES]> = StaticCell::new();
|
static SW_RX_RING: StaticCell<[u8; RX_RING_BYTES]> = StaticCell::new();
|
||||||
static RAW_BITS_CHANNEL: Channel<CriticalSectionRawMutex, u8, 4096> = Channel::new();
|
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(spawner: Spawner) {
|
async fn main(spawner: Spawner) {
|
||||||
info!("boot");
|
info!("boot");
|
||||||
let p = embassy_stm32::init(Default::default());
|
let p = embassy_stm32::init(Default::default());
|
||||||
info!("init m8");
|
info!("init m8");
|
||||||
|
|
||||||
|
|
||||||
// HARDWARE UART to the PC
|
// HARDWARE UART to the PC
|
||||||
let mut cfg = Config::default();
|
let mut cfg = Config::default();
|
||||||
cfg.baudrate = BAUD;
|
cfg.baudrate = BAUD;
|
||||||
@@ -67,7 +63,7 @@ async fn main(spawner: Spawner) {
|
|||||||
Irqs,
|
Irqs,
|
||||||
cfg,
|
cfg,
|
||||||
).unwrap();
|
).unwrap();
|
||||||
let _ = usart1::setup_and_spawn(BAUD);
|
let yield_period = usart1::setup_and_spawn(BAUD);
|
||||||
spawner.spawn(uart_task(uart, &PIPE_HW_TX, &PIPE_HW_RX).unwrap());
|
spawner.spawn(uart_task(uart, &PIPE_HW_TX, &PIPE_HW_RX).unwrap());
|
||||||
// END OF HARDWARE UART to the PC
|
// END OF HARDWARE UART to the PC
|
||||||
|
|
||||||
@@ -86,6 +82,7 @@ async fn main(spawner: Spawner) {
|
|||||||
Irqs2,
|
Irqs2,
|
||||||
cfg2,
|
cfg2,
|
||||||
).unwrap();
|
).unwrap();
|
||||||
|
|
||||||
let _ = usart2::setup_and_spawn(BAUD);
|
let _ = usart2::setup_and_spawn(BAUD);
|
||||||
spawner.spawn(uart_task_internal(uart2, &PIPE_INT_TX, &PIPE_INT_RX).unwrap());
|
spawner.spawn(uart_task_internal(uart2, &PIPE_INT_TX, &PIPE_INT_RX).unwrap());
|
||||||
info!("USART2 ready");
|
info!("USART2 ready");
|
||||||
@@ -97,66 +94,37 @@ async fn main(spawner: Spawner) {
|
|||||||
info!("USART1 <-> USART2 bridge active");
|
info!("USART1 <-> USART2 bridge active");
|
||||||
// END OF USART1 <-> USART2 bridge
|
// END OF USART1 <-> USART2 bridge
|
||||||
|
|
||||||
// SOFTWARE UART CONFIG
|
// SOFTWARE UART
|
||||||
// We initialize the Input here to ensure GPIO is configured (PullUp, etc.)
|
// let _rx = Input::new(p.PD6, Pull::Up);
|
||||||
let mut rx_pin = Input::new(p.PD6, Pull::Up);
|
let rx_pin = Input::new(p.PD6, Pull::Up);
|
||||||
|
// Configure TX as output (PB0)
|
||||||
use cortex_m::interrupt::free;
|
|
||||||
let rx_pin_ref: &'static mut Input<'static> = unsafe { core::mem::transmute(&mut rx_pin) };
|
|
||||||
free(|cs| RX_PIN_GLOBAL.borrow(cs).replace(Some(rx_pin_ref)));
|
|
||||||
|
|
||||||
|
let mut tx_pin = Output::new(p.PB0, Level::High, Speed::VeryHigh);
|
||||||
init_tim6_for_uart(p.TIM6, BAUD, TX_OVERSAMPLE);
|
init_tim6_for_uart(p.TIM6, BAUD, TX_OVERSAMPLE);
|
||||||
|
|
||||||
// Init TIM7 with Interrupt enabled (see dma_timer.rs)
|
|
||||||
init_tim7_for_uart(p.TIM7, BAUD, RX_OVERSAMPLE);
|
init_tim7_for_uart(p.TIM7, BAUD, RX_OVERSAMPLE);
|
||||||
dump_tim6_regs();
|
dump_tim6_regs();
|
||||||
|
// EDN OF SOFTWARE UART
|
||||||
// Enable TIM7 Interrupt in NVIC
|
|
||||||
unsafe {
|
|
||||||
cortex_m::peripheral::NVIC::unmask(pac::Interrupt::TIM7);
|
|
||||||
}
|
|
||||||
info!("TIM7 Interrupt enabled");
|
|
||||||
// END OF SOFTWARE UART
|
|
||||||
|
|
||||||
|
|
||||||
|
let mut last_yield = Instant::now();
|
||||||
|
let mut buf = [0u8; 32];
|
||||||
|
|
||||||
let mut last_val = 0;
|
let mut last_state: u8 = 0;
|
||||||
let mut count = 0u32;
|
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
// Receive next bit from ISR (yields if empty)
|
// info!("tick start");
|
||||||
let val = RAW_BITS_CHANNEL.receive().await;
|
// Timer::after(Duration::from_millis(100)).await;
|
||||||
|
// info!("tick end");
|
||||||
|
|
||||||
if val != last_val {
|
// let n1 = PIPE_HW_RX.read(&mut buf).await;
|
||||||
info!("PD6 bit changed: {} (after {} stable ticks)", val, count);
|
// if n1 > 0 {
|
||||||
last_val = val;
|
// info!("PC received: {:a}", &buf[..n1]);
|
||||||
count = 0;
|
// let _ = PIPE_SW_TX.write(&buf[..n1]).await;
|
||||||
} else {
|
// info!("SW UART TX sent echo: {:a}", &buf[..n1]);
|
||||||
count += 1;
|
// }
|
||||||
}
|
// yield_now().await;
|
||||||
|
|
||||||
// CRITICAL: Yield periodically.
|
|
||||||
// The ISR produces 153,600 samples/s. Processing them one-by-one
|
|
||||||
// will starve the UART Bridge tasks if we don't yield explicitly.
|
|
||||||
if count % 128 == 0 {
|
|
||||||
yield_now().await;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[interrupt]
|
yield_now().await;
|
||||||
fn TIM7() {
|
|
||||||
let tim = unsafe { pac::TIM7 };
|
|
||||||
|
|
||||||
if tim.sr().read().uif() {
|
|
||||||
tim.sr().modify(|w| w.set_uif(false));
|
|
||||||
|
|
||||||
cortex_m::interrupt::free(|cs| {
|
|
||||||
if let Some(pin) = RX_PIN_GLOBAL.borrow(cs).borrow_mut().as_mut() {
|
|
||||||
let val = if pin.is_high() { 1u8 } else { 0u8 };
|
|
||||||
let _ = RAW_BITS_CHANNEL.try_send(val);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,7 +138,7 @@ pub async fn bridge_usart1_rx_to_usart2_tx(
|
|||||||
let n = usart1_rx.read(&mut buf).await;
|
let n = usart1_rx.read(&mut buf).await;
|
||||||
if n > 0 {
|
if n > 0 {
|
||||||
let _ = usart2_tx.write(&buf[..n]).await;
|
let _ = usart2_tx.write(&buf[..n]).await;
|
||||||
info!("Buffer USART1 -> USART2 bytes: {:?}", &buf[..n]);
|
info!("bridge: USART1 -> USART2 sent {} bytes", n);
|
||||||
}
|
}
|
||||||
yield_now().await;
|
yield_now().await;
|
||||||
}
|
}
|
||||||
@@ -186,7 +154,7 @@ pub async fn bridge_usart2_rx_to_usart1_tx(
|
|||||||
let n = usart2_rx.read(&mut buf).await;
|
let n = usart2_rx.read(&mut buf).await;
|
||||||
if n > 0 {
|
if n > 0 {
|
||||||
let _ = usart1_tx.write(&buf[..n]).await;
|
let _ = usart1_tx.write(&buf[..n]).await;
|
||||||
// info!("Buffer USART2 -> USART1 bytes: {:?}", &buf[..n]);
|
// info!("bridge: USART2 -> USART1 sent {} bytes", n);
|
||||||
}
|
}
|
||||||
yield_now().await;
|
yield_now().await;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// src/software_uart/dma_timer.rs
|
// src/dma_timer.rs
|
||||||
|
|
||||||
use embassy_stm32::{
|
use embassy_stm32::{
|
||||||
peripherals::{TIM6, TIM7},
|
peripherals::{TIM6, TIM7},
|
||||||
@@ -20,19 +20,11 @@ pub fn init_tim6_for_uart<'d>(tim6: Peri<'d, TIM6>, baud: u32, oversample: u16)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Initializes TIM7 to tick at `baud * oversample` frequency.
|
/// Initializes TIM7 to tick at `baud * oversample` frequency.
|
||||||
/// Each TIM7 update event triggers one DMA beat AND an Interrupt.
|
/// Each TIM7 update event triggers one DMA beat.
|
||||||
pub fn init_tim7_for_uart<'d>(tim7: Peri<'d, TIM7>, baud: u32, oversample: u16) {
|
pub fn init_tim7_for_uart<'d>(tim7: Peri<'d, TIM7>, baud: u32, oversample: u16) {
|
||||||
rcc::enable_and_reset::<TIM7>();
|
rcc::enable_and_reset::<TIM7>();
|
||||||
let ll = Timer::new(tim7);
|
let ll = Timer::new(tim7);
|
||||||
|
|
||||||
// Reuse the common config first
|
|
||||||
configure_basic_timer(&ll, baud, oversample);
|
configure_basic_timer(&ll, baud, oversample);
|
||||||
|
|
||||||
// Enable Update Interrupt (UIE) specifically for TIM7
|
|
||||||
ll.regs_basic().dier().modify(|w| {
|
|
||||||
w.set_uie(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
mem::forget(ll);
|
mem::forget(ll);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,9 +46,7 @@ fn configure_basic_timer<T: BasicInstance>(ll: &Timer<'_, T>, baud: u32, oversam
|
|||||||
|
|
||||||
ll.regs_basic().psc().write_value(0u16);
|
ll.regs_basic().psc().write_value(0u16);
|
||||||
ll.regs_basic().arr().write(|w| w.set_arr(arr));
|
ll.regs_basic().arr().write(|w| w.set_arr(arr));
|
||||||
|
|
||||||
ll.regs_basic().dier().modify(|w| w.set_ude(true));
|
ll.regs_basic().dier().modify(|w| w.set_ude(true));
|
||||||
|
|
||||||
ll.regs_basic().egr().write(|w| w.set_ug(true));
|
ll.regs_basic().egr().write(|w| w.set_ug(true));
|
||||||
|
|
||||||
ll.regs_basic().cr1().write(|w| {
|
ll.regs_basic().cr1().write(|w| {
|
||||||
|
|||||||
Reference in New Issue
Block a user