From 9c26a0ca81906145cb9bfb3d1469cc4b5599e234 Mon Sep 17 00:00:00 2001 From: Priec Date: Wed, 19 Nov 2025 11:57:28 +0100 Subject: [PATCH] not working interrupt via tim7 to read data --- semestralka_1d_rx_bez_dma/src/bin/main.rs | 109 ++++++++++-------- .../src/software_uart/dma_timer.rs | 16 ++- 2 files changed, 75 insertions(+), 50 deletions(-) diff --git a/semestralka_1d_rx_bez_dma/src/bin/main.rs b/semestralka_1d_rx_bez_dma/src/bin/main.rs index 56fc232..bed0158 100644 --- a/semestralka_1d_rx_bez_dma/src/bin/main.rs +++ b/semestralka_1d_rx_bez_dma/src/bin/main.rs @@ -4,17 +4,14 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_time::Instant; use embassy_stm32::dma::Request; -use embassy_stm32::gpio::{Input, Output, Level, Pull, Speed}; +use embassy_stm32::gpio::{Input, Pull}; use dma_gpio::software_uart::{ dma_timer::{init_tim6_for_uart, init_tim7_for_uart}, - gpio_dma_uart_rx::rx_dma_task, debug::dump_tim6_regs, }; use dma_gpio::config::{BAUD, RX_OVERSAMPLE, TX_OVERSAMPLE}; 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 embassy_futures::yield_now; use dma_gpio::hw_uart_pc::usart1; @@ -22,17 +19,22 @@ use dma_gpio::hw_uart_pc::driver::uart_task; use embassy_stm32::usart::{BufferedUart, Config, BufferedInterruptHandler}; use embassy_stm32::peripherals; use embassy_stm32::bind_interrupts; -use dma_gpio::config::{PIPE_HW_TX, PIPE_HW_RX, PIPE_SW_TX, PIPE_SW_RX}; +use dma_gpio::config::{PIPE_HW_TX, PIPE_HW_RX}; use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, pipe::Pipe}; use dma_gpio::hw_uart_internal::usart2; 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::software_uart::uart_emulation::decode_uart_samples; -use dma_gpio::config::UART_CFG; -use embassy_stm32::pac::TIM6; +use embassy_stm32::pac; +use embassy_stm32::interrupt; use embassy_time::{Duration, Timer}; +use embassy_sync::channel::Channel; use {defmt_rtt as _, panic_probe as _}; +use cortex_m::interrupt::Mutex; +use core::cell::RefCell; + +static RX_PIN_GLOBAL: Mutex>>> = Mutex::new(RefCell::new(None)); + bind_interrupts!(struct Irqs { USART1 => BufferedInterruptHandler; }); @@ -44,6 +46,7 @@ bind_interrupts!(struct Irqs2 { pub const TIM6_UP_REQ: Request = 4; static SW_TX_RING: StaticCell<[u32; TX_RING_BYTES]> = StaticCell::new(); static SW_RX_RING: StaticCell<[u8; RX_RING_BYTES]> = StaticCell::new(); +static RAW_BITS_CHANNEL: Channel = Channel::new(); #[embassy_executor::main] async fn main(spawner: Spawner) { @@ -64,12 +67,10 @@ async fn main(spawner: Spawner) { Irqs, cfg, ).unwrap(); - let yield_period = usart1::setup_and_spawn(BAUD); + let _ = usart1::setup_and_spawn(BAUD); spawner.spawn(uart_task(uart, &PIPE_HW_TX, &PIPE_HW_RX).unwrap()); // END OF HARDWARE UART to the PC - - // INTERNAL HARDWARE UART (USART2) let mut cfg2 = Config::default(); cfg2.baudrate = BAUD; @@ -89,59 +90,73 @@ async fn main(spawner: Spawner) { spawner.spawn(uart_task_internal(uart2, &PIPE_INT_TX, &PIPE_INT_RX).unwrap()); info!("USART2 ready"); // END OF INTERNAL HARDWARE UART (USART2) - + // USART1 <-> USART2 bridge spawner.spawn(bridge_usart1_rx_to_usart2_tx(&PIPE_HW_RX, &PIPE_INT_TX).unwrap()); spawner.spawn(bridge_usart2_rx_to_usart1_tx(&PIPE_INT_RX, &PIPE_HW_TX).unwrap()); info!("USART1 <-> USART2 bridge active"); - // END OF USART1 <-> USART2 bridge + // END OF USART1 <-> USART2 bridge + // SOFTWARE UART CONFIG + // We initialize the Input here to ensure GPIO is configured (PullUp, etc.) + let mut rx_pin = Input::new(p.PD6, Pull::Up); - - // SOFTWARE UART - // let _rx = Input::new(p.PD6, Pull::Up); - let rx_pin = Input::new(p.PD6, Pull::Up); - // let tx_pin = Output::new(p.PB0, Level::High, Speed::VeryHigh); + 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))); + 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); 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 tim6_regs = TIM6; - let mut levels = [0u8; 512]; - let mut idx = 0usize; - let mut buf = [0u8; 32]; - let mut last_state: u8 = 0; + let mut last_val = 0; + let mut count = 0u32; + loop { - // info!("tick start"); + // Receive next bit from ISR (yields if empty) + let val = RAW_BITS_CHANNEL.receive().await; - // RX pin should be READ in here and print via info! - // - while !tim6_regs.sr().read().uif() { + if val != last_val { + info!("PD6 bit changed: {} (after {} stable ticks)", val, count); + last_val = val; + count = 0; + } else { + count += 1; + } + + // 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; } - tim6_regs.sr().modify(|w| w.set_uif(false)); - let bit = rx_pin.is_high(); - levels[idx] = bit as u8; - idx += 1; + } +} - // When buffer full, decode UART samples into bytes - if idx >= levels.len() { - let decoded = decode_uart_samples(&levels, RX_OVERSAMPLE, &UART_CFG); - if !decoded.is_empty() { - info!("SW RX decoded: {:a}", decoded.as_slice()); +#[interrupt] +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); } - idx = 0; - } - - // let n1 = PIPE_INT_TX.read(&mut buf).await; - // if n1 > 0 { - // info!("PIPE_INT_TX received: {:a}", &buf[..n1]); - // } - - Timer::after(Duration::from_millis(1)).await; - yield_now().await; + }); } } diff --git a/semestralka_1d_rx_bez_dma/src/software_uart/dma_timer.rs b/semestralka_1d_rx_bez_dma/src/software_uart/dma_timer.rs index 6979383..084f8ab 100644 --- a/semestralka_1d_rx_bez_dma/src/software_uart/dma_timer.rs +++ b/semestralka_1d_rx_bez_dma/src/software_uart/dma_timer.rs @@ -1,4 +1,4 @@ -// src/dma_timer.rs +// src/software_uart/dma_timer.rs use embassy_stm32::{ peripherals::{TIM6, TIM7}, @@ -20,11 +20,19 @@ pub fn init_tim6_for_uart<'d>(tim6: Peri<'d, TIM6>, baud: u32, oversample: u16) } /// Initializes TIM7 to tick at `baud * oversample` frequency. -/// Each TIM7 update event triggers one DMA beat. +/// Each TIM7 update event triggers one DMA beat AND an Interrupt. pub fn init_tim7_for_uart<'d>(tim7: Peri<'d, TIM7>, baud: u32, oversample: u16) { rcc::enable_and_reset::(); let ll = Timer::new(tim7); + + // Reuse the common config first 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); } @@ -46,7 +54,9 @@ fn configure_basic_timer(ll: &Timer<'_, T>, baud: u32, oversam ll.regs_basic().psc().write_value(0u16); 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().cr1().write(|w| {