From 4f5659b849620dc909d0ff1a3261204931d5c5ed Mon Sep 17 00:00:00 2001 From: Per Lindgren <per.lindgren@ltu.se> Date: Sun, 11 Feb 2018 13:49:10 +0100 Subject: [PATCH] now interrupt works for send --- .vscode/launch.json | 44 +++++++----- examples/rtfm-serial-dma-tx.rs | 120 +++++++++++++++++++++++++++++++++ src/dma.rs | 27 +++++--- src/serial.rs | 42 ++---------- 4 files changed, 169 insertions(+), 64 deletions(-) create mode 100644 examples/rtfm-serial-dma-tx.rs diff --git a/.vscode/launch.json b/.vscode/launch.json index 9d29e47..6bd3c7c 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -86,25 +86,37 @@ "type": "cortex-debug", "request": "launch", "servertype": "openocd", - "name": "Debug Microcontroller", + "name": "c serial-dma-tx", "executable": "./target/thumbv7em-none-eabihf/debug/examples/serial-dma-tx", "configFiles": [ "interface/stlink.cfg", "target/stm32f4x.cfg" ], - "swoConfig": [ - "enabled": "true", - "swoFrequency": "0", - "cpuFrequency": "0", - "ports": [ - [ - "number": "0", - "label": "0", - "format": "console", - ] - ] - ], - "cwd": "${workspaceRoot}" - } - ] + // "swoConfig": [ + // "enabled": "true", + // "swoFrequency": "0", + // "cpuFrequency": "0", + // "ports": [ + // [ + // "number": "0", + // "label": "0", + // "format": "console", + // ] + // ] + ], + "cwd": "${workspaceRoot}" + }, + { + "type": "cortex-debug", + "request": "launch", + "servertype": "openocd", + "name": "c rtfm-serial-dma-tx", + "executable": "./target/thumbv7em-none-eabihf/debug/examples/rtfm-serial-dma-tx", + "configFiles": [ + "interface/stlink.cfg", + "target/stm32f4x.cfg" + ], + "cwd": "${workspaceRoot}" + } +] } \ No newline at end of file diff --git a/examples/rtfm-serial-dma-tx.rs b/examples/rtfm-serial-dma-tx.rs new file mode 100644 index 0000000..be8f03b --- /dev/null +++ b/examples/rtfm-serial-dma-tx.rs @@ -0,0 +1,120 @@ +//! Serial interface echo server (reactive version) +//! +//! This is a reactive version of the `serial-echo` example. Here the processor sleeps most of the +//! time and only wakes up to sent back received bytes. +//! +//! This example uses the [Real Time For the Masses framework](https://docs.rs/cortex-m-rtfm/~0.3) +#![deny(unsafe_code)] +//#![deny(warnings)] +#![feature(proc_macro)] +#![no_std] + +extern crate cortex_m; +extern crate cortex_m_rtfm as rtfm; +extern crate stm32f4x_hal as hal; + +use hal::prelude::*; +use hal::serial::{Rx, Serial, Tx}; +use hal::dma::Event; +use hal::stm32f4x; +use rtfm::{app, Threshold}; +use cortex_m::asm; + +app! { + device: stm32f4x, + + resources: { + //static TX: Tx<stm32f4x::USART2>; + static RX: Rx<stm32f4x::USART2>; + }, + + tasks: { + DMA1_STREAM6: { + path: tx, + resources: [RX], + } + }, +} + +fn init(p: init::Peripherals) -> init::LateResources { + let mut flash = p.device.FLASH.constrain(); + let mut rcc = p.device.RCC.constrain(); + let mut gpioa = p.device.GPIOA.split(&mut rcc.ahb1); + let streams = p.device.DMA1.split(&mut rcc.ahb1); + let mut tx_stream = streams.1.into_channel4(); // S6<C4> + + let clocks = rcc.cfgr.freeze(&mut flash.acr); + + let tx = gpioa.pa2.into_af7(&mut gpioa.moder, &mut gpioa.afrl); + let rx = gpioa.pa3.into_af7(&mut gpioa.moder, &mut gpioa.afrl); + + let mut serial = Serial::usart2( + p.device.USART2, + (tx, rx), + 115_200.bps(), + clocks, + &mut rcc.apb1, + ); + + let (tx, rx) = serial.split(); + tx_stream.listen(Event::TransferComplete); + + let _ = tx.write_all(tx_stream, b"The quick brown fox"); + + init::LateResources { RX: rx } +} + +fn idle() -> ! { + // sleep + loop { + // rtfm::wfi(); + } +} + +fn tx(_: &mut Threshold, mut r: DMA1_STREAM6::Resources) { + asm::bkpt(); +} + +// //! Serial interface echo server +// //! +// //! In this example every received byte will be sent back to the sender. You can test this example +// //! with serial terminal emulator like `minicom`. +// #![deny(unsafe_code)] +// //#![deny(warnings)] +// #![no_std] + +// extern crate stm32f4x_hal as f4; + +// use f4::prelude::*; +// use f4::serial::Serial; +// use f4::stm32f4x; + +// fn main() { +// let p = stm32f4x::Peripherals::take().unwrap(); + +// let mut flash = p.FLASH.constrain(); +// let mut rcc = p.RCC.constrain(); +// let mut gpioa = p.GPIOA.split(&mut rcc.ahb1); +// let streams = p.DMA1.split(&mut rcc.ahb1); +// let tx_stream = streams.1.into_channel4(); // S6<C4> + +// let clocks = rcc.cfgr.freeze(&mut flash.acr); + +// let tx = gpioa.pa2.into_af7(&mut gpioa.moder, &mut gpioa.afrl); +// let rx = gpioa.pa3.into_af7(&mut gpioa.moder, &mut gpioa.afrl); + +// let serial = Serial::usart2(p.USART2, (tx, rx), 115_200.bps(), clocks, &mut rcc.apb1); +// let (mut tx, mut rx) = serial.split(); + +// let (_, c, tx) = tx.write_all(tx_stream, b"The quick brown fox").wait(); + +// // asm::bkpt(); + +// let (_, c, tx) = tx.write_all(c, b" jumps").wait(); + +// // asm::bkpt(); + +// tx.write_all(c, b" over the lazy dog.").wait(); + +// // asm::bkpt(); +// } diff --git a/src/dma.rs b/src/dma.rs index 62d67d7..f176508 100644 --- a/src/dma.rs +++ b/src/dma.rs @@ -206,11 +206,20 @@ pub mod dma1 { impl<CHANNEL> S5<CHANNEL> { pub fn listen(&mut self, event: Event) { + let dma = unsafe { &*DMA1::ptr() }; + match event { + Event::HalfTransfer => dma.s5cr.modify(|_, w| w.htie().set_bit()), + Event::TransferComplete => dma.s5cr.modify(|_, w| w.tcie().set_bit()), + } + } + } + + impl<CHANNEL> S6<CHANNEL> { + pub fn listen(&mut self, event: Event) { + let dma = unsafe { &*DMA1::ptr() }; match event { - Event::HalfTransfer => (), // self.ccr().modify(|_, w| w.htie().set_bit()), - Event::TransferComplete => { - // self.ccr().modify(|_, w| w.tcie().set_bit()) - } + Event::HalfTransfer => dma.s6cr.modify(|_, w| w.htie().set_bit()), + Event::TransferComplete => dma.s6cr.modify(|_, w| w.tcie().set_bit()), } } } @@ -235,9 +244,9 @@ pub mod dma1 { // pinc: Peripheral increment mode disabled // circ: Circular mode disabled // dir: Transfer from memory to peripheral - // tcie: Transfer complete interrupt enabled + // en: Disabled - dma.s6cr.write(|w| unsafe { + dma.s6cr.modify(|_, w| unsafe { w.chsel() .bits(4) // channel 4 .pl() @@ -254,12 +263,10 @@ pub mod dma1 { .clear_bit() // no peripheral increment .dir() .bits(1) // memory -> peripheral - .tcie() - .clear_bit() // no interrupt .en() - .clear_bit() // setup + .set_bit() // setup }); - dma.s6cr.modify(|_, w| w.en().set_bit()); + // dma.s6cr.modify(|_, w| w.en().set_bit()); } impl DmaExt for DMA1 { diff --git a/src/serial.rs b/src/serial.rs index c37a132..5a16c3d 100644 --- a/src/serial.rs +++ b/src/serial.rs @@ -276,45 +276,11 @@ macro_rules! hal { buf.as_ptr() as u32 ); - - //let buffer: &[u8] = buffer.borrow(); - // chan.cmar().write(|w| unsafe { - // w.ma().bits(buffer.as_ptr() as usize as u32) - // }); - // chan.cndtr().write(|w| unsafe{ - // w.ndt().bits(u16(buffer.len()).unwrap()) - // }); - // chan.cpar().write(|w| unsafe { - // w.pa().bits(&(*$USARTX::ptr()).dr as *const _ as usize as u32) - // }); - - // TODO can we weaken this compiler barrier? - // NOTE(compiler_fence) operations on `buffer` should not be reordered after - // the next statement, which starts the DMA transfer - // atomic::compiler_fence(Ordering::SeqCst); - - // chan.ccr().modify(|_, w| { - // w.mem2mem() - // .clear_bit() - // .pl() - // .medium() - // .msize() - // .bit8() - // .psize() - // .bit8() - // .minc() - // .set_bit() - // .pinc()chan - // .clear_bit() - // .circ() - // .clear_bit() - // .dir() - // .set_bit() - // .en() - // .set_bit() - // }); + // TODO can we weaken this compiler barrier? + // NOTE(compiler_fence) operations on `buffer` should not be reordered after + // the next statement, which starts the DMA transfer + atomic::compiler_fence(Ordering::SeqCst); } - Transfer::r(buffer, tx_stream, self) } } -- GitLab