not working interrupt via tim7 to read data

This commit is contained in:
Priec
2025-11-19 11:57:28 +01:00
parent c5bee53a30
commit 9c26a0ca81
2 changed files with 75 additions and 50 deletions

View File

@@ -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<RefCell<Option<&'static mut Input<'static>>>> = Mutex::new(RefCell::new(None));
bind_interrupts!(struct Irqs {
USART1 => BufferedInterruptHandler<peripherals::USART1>;
});
@@ -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<CriticalSectionRawMutex, u8, 4096> = 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;
@@ -96,52 +97,66 @@ async fn main(spawner: Spawner) {
info!("USART1 <-> USART2 bridge active");
// 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);
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)));
// 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);
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());
}
idx = 0;
}
#[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);
}
// 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;
});
}
}

View File

@@ -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::<TIM7>();
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<T: BasicInstance>(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().egr().write(|w| w.set_ug(true));
ll.regs_basic().cr1().write(|w| {