Skip to content
Snippets Groups Projects
Commit 32347613 authored by Per Lindgren's avatar Per Lindgren
Browse files

receive example works still experimental

parent 324119ea
No related branches found
No related tags found
No related merge requests found
...@@ -4,84 +4,84 @@ ...@@ -4,84 +4,84 @@
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0", "version": "0.2.0",
"configurations": [ "configurations": [
{ // {
"type": "gdb", // "type": "gdb",
"request": "attach", // "request": "attach",
"name": "hello_debug", // "name": "hello_debug",
"gdbpath": "/usr/bin/arm-none-eabi-gdb", // "gdbpath": "/usr/bin/arm-none-eabi-gdb",
"executable": "./target/thumbv7em-none-eabihf/debug/examples/hello_debug", // "executable": "./target/thumbv7em-none-eabihf/debug/examples/hello_debug",
"target": ":3333", // "target": ":3333",
"remote": true, // "remote": true,
"autorun": [ // "autorun": [
"load", // "load",
], // ],
"cwd": "${workspaceRoot}" // "cwd": "${workspaceRoot}"
}, // },
{ // {
"type": "gdb", // "type": "gdb",
"request": "attach", // "request": "attach",
"name": "serial-echo", // "name": "serial-echo",
"gdbpath": "/usr/bin/arm-none-eabi-gdb", // "gdbpath": "/usr/bin/arm-none-eabi-gdb",
"executable": "./target/thumbv7em-none-eabihf/debug/examples/serial-echo", // "executable": "./target/thumbv7em-none-eabihf/debug/examples/serial-echo",
"target": ":3333", // "target": ":3333",
"remote": true, // "remote": true,
"autorun": [ // "autorun": [
"load" // "load"
], // ],
"cwd": "${workspaceRoot}" // "cwd": "${workspaceRoot}"
}, // },
{ // {
"type": "gdb", // "type": "gdb",
"request": "attach", // "request": "attach",
"name": "rtfm-blinky-systic", // "name": "rtfm-blinky-systic",
"gdbpath": "/usr/bin/arm-none-eabi-gdb", // "gdbpath": "/usr/bin/arm-none-eabi-gdb",
"executable": "./target/thumbv7em-none-eabihf/debug/examples/rtfm-blinky-systic", // "executable": "./target/thumbv7em-none-eabihf/debug/examples/rtfm-blinky-systic",
"target": ":3333", // "target": ":3333",
"remote": true, // "remote": true,
"autorun": [ // "autorun": [
"load" // "load"
], // ],
"cwd": "${workspaceRoot}" // "cwd": "${workspaceRoot}"
}, // },
{ // {
"type": "gdb", // "type": "gdb",
"request": "attach", // "request": "attach",
"name": "rtfm-blinky-tim2", // "name": "rtfm-blinky-tim2",
"gdbpath": "/usr/bin/arm-none-eabi-gdb", // "gdbpath": "/usr/bin/arm-none-eabi-gdb",
"executable": "./target/thumbv7em-none-eabihf/debug/examples/rtfm-blinky-tim2", // "executable": "./target/thumbv7em-none-eabihf/debug/examples/rtfm-blinky-tim2",
"target": ":3333", // "target": ":3333",
"remote": true, // "remote": true,
"autorun": [ // "autorun": [
"load" // "load"
], // ],
"cwd": "${workspaceRoot}" // "cwd": "${workspaceRoot}"
}, // },
{ // {
"type": "gdb", // "type": "gdb",
"request": "attach", // "request": "attach",
"name": "rtfm-serial-echo", // "name": "rtfm-serial-echo",
"gdbpath": "/usr/bin/arm-none-eabi-gdb", // "gdbpath": "/usr/bin/arm-none-eabi-gdb",
"executable": "./target/thumbv7em-none-eabihf/debug/examples/rtfm-serial-echo", // "executable": "./target/thumbv7em-none-eabihf/debug/examples/rtfm-serial-echo",
"target": ":3333", // "target": ":3333",
"remote": true, // "remote": true,
"autorun": [ // "autorun": [
"load" // "load"
], // ],
"cwd": "${workspaceRoot}" // "cwd": "${workspaceRoot}"
}, // },
{ // {
"type": "gdb", // "type": "gdb",
"request": "attach", // "request": "attach",
"name": "serial-dma-tx", // "name": "serial-dma-tx",
"gdbpath": "/usr/bin/arm-none-eabi-gdb", // "gdbpath": "/usr/bin/arm-none-eabi-gdb",
"executable": "./target/thumbv7em-none-eabihf/debug/examples/serial-dma-tx", // "executable": "./target/thumbv7em-none-eabihf/debug/examples/serial-dma-tx",
"target": ":3333", // "target": ":3333",
"remote": true, // "remote": true,
"autorun": [ // "autorun": [
"load" // "load"
], // ],
"cwd": "${workspaceRoot}" // "cwd": "${workspaceRoot}"
}, // },
{ {
"type": "cortex-debug", "type": "cortex-debug",
"request": "launch", "request": "launch",
...@@ -117,6 +117,18 @@ ...@@ -117,6 +117,18 @@
"target/stm32f4x.cfg" "target/stm32f4x.cfg"
], ],
"cwd": "${workspaceRoot}" "cwd": "${workspaceRoot}"
},
{
"type": "cortex-debug",
"request": "launch",
"servertype": "openocd",
"name": "c serial-dma-rx",
"executable": "./target/thumbv7em-none-eabihf/debug/examples/serial-dma-rx",
"configFiles": [
"interface/stlink.cfg",
"target/stm32f4x.cfg"
],
"cwd": "${workspaceRoot}"
} }
] ]
} }
\ No newline at end of file
//! 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]
#[macro_use(singleton)]
extern crate cortex_m;
extern crate stm32f4x_hal as f4;
use cortex_m::asm;
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 rx_stream = streams.0.into_channel4(); // S5<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 buf = singleton!(: [u8; 8] = [0; 8]).unwrap();
let (_buf, _c, _rx) = rx.read_exact(rx_stream, buf).wait();
asm::bkpt();
}
//! Serial interface echo server //! Serial interface with dma
//!
//! 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(unsafe_code)]
//#![deny(warnings)] #![deny(warnings)]
#![no_std] #![no_std]
extern crate cortex_m;
extern crate stm32f4x_hal as f4; extern crate stm32f4x_hal as f4;
use cortex_m::asm;
use f4::prelude::*; use f4::prelude::*;
use f4::serial::Serial; use f4::serial::Serial;
use f4::stm32f4x; use f4::stm32f4x;
...@@ -27,17 +27,17 @@ fn main() { ...@@ -27,17 +27,17 @@ fn main() {
let rx = gpioa.pa3.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 serial = Serial::usart2(p.USART2, (tx, rx), 115_200.bps(), clocks, &mut rcc.apb1);
let (mut tx, mut rx) = serial.split(); let (tx, _) = serial.split();
let (_, c, tx) = tx.write_all(tx_stream, b"The quick brown fox").wait(); let (_, c, tx) = tx.write_all(tx_stream, b"The quick brown fox").wait();
// asm::bkpt(); asm::bkpt();
let (_, c, tx) = tx.write_all(c, b" jumps").wait(); let (_, c, tx) = tx.write_all(c, b" jumps").wait();
// asm::bkpt(); asm::bkpt();
tx.write_all(c, b" over the lazy dog.").wait(); tx.write_all(c, b" over the lazy dog.").wait();
// asm::bkpt(); asm::bkpt();
} }
...@@ -126,7 +126,9 @@ pub unsafe trait UsartTxStream<USART> { ...@@ -126,7 +126,9 @@ pub unsafe trait UsartTxStream<USART> {
fn start_transfer(&mut self, ndtr: u16, par: u32, m0: u32); fn start_transfer(&mut self, ndtr: u16, par: u32, m0: u32);
} }
pub unsafe trait UsartRxStream<USART> {} pub unsafe trait UsartRxStream<USART> {
fn start_transfer(&mut self, ndtr: u16, par: u32, m0: u32);
}
pub mod dma1 { pub mod dma1 {
use core::sync::atomic::{self, Ordering}; use core::sync::atomic::{self, Ordering};
...@@ -155,7 +157,6 @@ pub mod dma1 { ...@@ -155,7 +157,6 @@ pub mod dma1 {
pub struct S7<CHANNEL> { pub struct S7<CHANNEL> {
_channel: PhantomData<CHANNEL>, _channel: PhantomData<CHANNEL>,
} }
//pub struct S7<CHANNEL> {}
// Channels === Alternate function // Channels === Alternate function
pub struct C0; pub struct C0;
...@@ -196,11 +197,15 @@ pub mod dma1 { ...@@ -196,11 +197,15 @@ pub mod dma1 {
unsafe impl super::UsartTxStream<USART2> for S6<C4> { unsafe impl super::UsartTxStream<USART2> for S6<C4> {
fn start_transfer(&mut self, ndtr: u16, par: u32, m0: u32) { fn start_transfer(&mut self, ndtr: u16, par: u32, m0: u32) {
start_transfer_s6_c4(ndtr, par, m0); start_transfer_s6(4, ndtr, par, m0);
}
}
unsafe impl super::UsartRxStream<USART2> for S5<C4> {
fn start_transfer(&mut self, ndtr: u16, par: u32, m0: u32) {
start_transfer_s5(4, ndtr, par, m0);
} }
} }
unsafe impl super::UsartRxStream<USART2> for S5<C4> {}
unsafe impl super::UsartRxStream<USART2> for S7<C6> {}
pub struct Streams(pub S5<C0>, pub S6<C0>, pub S7<C0>); pub struct Streams(pub S5<C0>, pub S6<C0>, pub S7<C0>);
...@@ -226,7 +231,8 @@ pub mod dma1 { ...@@ -226,7 +231,8 @@ pub mod dma1 {
use cortex_m::asm; use cortex_m::asm;
fn start_transfer_s6_c4(ndtr: u16, par: u32, m0: u32) { // should be generalized by macro
fn start_transfer_s6(channel: u8, ndtr: u16, par: u32, m0: u32) {
let dma = unsafe { &*DMA1::ptr() }; let dma = unsafe { &*DMA1::ptr() };
// nr data transfers // nr data transfers
...@@ -248,7 +254,7 @@ pub mod dma1 { ...@@ -248,7 +254,7 @@ pub mod dma1 {
// en: Disabled // en: Disabled
dma.s6cr.modify(|_, w| unsafe { dma.s6cr.modify(|_, w| unsafe {
w.chsel() w.chsel()
.bits(4) // channel 4 .bits(channel) // channel 4
.pl() .pl()
.bits(0b01) // medium priority .bits(0b01) // medium priority
.msize() .msize()
...@@ -264,11 +270,44 @@ pub mod dma1 { ...@@ -264,11 +270,44 @@ pub mod dma1 {
.dir() .dir()
.bits(1) // memory -> peripheral .bits(1) // memory -> peripheral
.en() .en()
.set_bit() // setup .set_bit() // enable
}); });
// dma.s6cr.modify(|_, w| w.en().set_bit()); // dma.s6cr.modify(|_, w| w.en().set_bit());
} }
fn start_transfer_s5(channel: u8, ndtr: u16, par: u32, m0: u32) {
let dma = unsafe { &*DMA1::ptr() };
// nr data transfers
dma.s5ndtr.write(|w| unsafe { w.ndt().bits(ndtr) });
// peripheral address
dma.s5par.write(|w| unsafe { w.bits(par) });
// memory address 0
dma.s5m0ar.write(|w| unsafe { w.bits(m0) });
// RX DMA transfer
dma.s5cr.modify(|_, w| unsafe {
w.chsel()
.bits(channel) // channel 4
.pl()
.bits(0b01) // medium priority
.msize()
.bits(0b00) // memory 8 bits
.psize()
.bits(0b00) // peripheral 8 bits
.minc() // memory increment
.set_bit()
.circ()
.clear_bit() // not circular
.pinc()
.clear_bit() // no peripheral increment
.dir()
.bits(0) // peripheral -> memory
.en()
.set_bit() // setup
});
}
impl DmaExt for DMA1 { impl DmaExt for DMA1 {
type Streams = Streams; type Streams = Streams;
...@@ -317,4 +356,25 @@ pub mod dma1 { ...@@ -317,4 +356,25 @@ pub mod dma1 {
(self.buffer, self.stream, self.payload) (self.buffer, self.stream, self.payload)
} }
} }
impl<BUFFER, PAYLOAD, MODE> Transfer<MODE, BUFFER, S5<C4>, PAYLOAD> {
pub fn wait(mut self) -> (BUFFER, S5<C4>, PAYLOAD) {
// XXX should we check for transfer errors here?
// The manual says "A DMA transfer error can be generated by reading
// from or writing to a reserved address space". I think it's impossible
// to get to that state with our type safe API and *safe* Rust.
let dma = unsafe { &*DMA1::ptr() };
while dma.hisr.read().tcif5().bit_is_clear() {}
dma.hifcr.write(|w| w.ctcif5().set_bit());
dma.s5cr.modify(|_, w| w.en().clear_bit());
// TODO can we weaken this compiler barrier?
// NOTE(compiler_fence) operations on `buffer` should not be reordered
// before the previous statement, which marks the DMA transfer as done
atomic::compiler_fence(Ordering::SeqCst);
(self.buffer, self.stream, self.payload)
}
}
} }
...@@ -13,7 +13,7 @@ use cast::u16; ...@@ -13,7 +13,7 @@ use cast::u16;
use hal::serial; use hal::serial;
use nb; use nb;
use stm32f4x::{USART1, USART2, USART6}; use stm32f4x::{USART1, USART2, USART6};
use dma::{Static, Transfer, UsartTxStream, R}; use dma::{Static, Transfer, UsartRxStream, UsartTxStream, R, W};
// usart2 // usart2
use gpio::gpioa::{PA2, PA3}; use gpio::gpioa::{PA2, PA3};
...@@ -101,7 +101,13 @@ pub struct Tx<USART> { ...@@ -101,7 +101,13 @@ pub struct Tx<USART> {
macro_rules! hal { macro_rules! hal {
($( ($(
$USARTX:ident: ($usartX:ident, $APB:ident, $usartXen:ident, $usartXrst:ident, $pclkX:ident), $USARTX:ident: (
$usartX:ident,
$APB:ident,
$usartXen:ident,
$usartXrst:ident,
$pclkX:ident
),
)+) => { )+) => {
$( $(
impl<TX, RX> Serial<$USARTX, (TX, RX)> { impl<TX, RX> Serial<$USARTX, (TX, RX)> {
...@@ -255,6 +261,7 @@ macro_rules! hal { ...@@ -255,6 +261,7 @@ macro_rules! hal {
} }
} }
} }
impl Tx<$USARTX> { impl Tx<$USARTX> {
pub fn write_all<A, B, S>( pub fn write_all<A, B, S>(
self, // should be mutable? self, // should be mutable?
...@@ -267,24 +274,53 @@ macro_rules! hal { ...@@ -267,24 +274,53 @@ macro_rules! hal {
S: UsartTxStream<$USARTX> S: UsartTxStream<$USARTX>
{ {
{ {
let buf :&[u8] = buffer.borrow(); let buffer :&[u8] = buffer.borrow();
// 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);
// ntdr, par, m0 // ntdr, par, m0
tx_stream.start_transfer( tx_stream.start_transfer(
u16(buf.len()).unwrap(), u16(buffer.len()).unwrap(),
unsafe { &(*$USARTX::ptr()).dr as *const _ as usize as u32 }, unsafe { &(*$USARTX::ptr()).dr as *const _ as usize as u32 },
buf.as_ptr() as u32 buffer.as_ptr() as u32
); );
}
Transfer::r(buffer, tx_stream, self)
}
}
impl Rx<$USARTX> {
pub fn read_exact<A, S>(
self,
mut rx_stream: S,
buffer: &'static mut A,
) -> Transfer<W, &'static mut A, S, Self>
where
A: Unsize<[u8]>,
S: UsartRxStream<$USARTX>
{
{
let buffer: &[u8] = buffer;
// TODO can we weaken this compiler barrier? // TODO can we weaken this compiler barrier?
// NOTE(compiler_fence) operations on `buffer` should not be reordered after // NOTE(compiler_fence) operations on `buffer` should not be reordered after
// the next statement, which starts the DMA transfer // the next statement, which starts the DMA transfer
atomic::compiler_fence(Ordering::SeqCst); atomic::compiler_fence(Ordering::SeqCst);
rx_stream.start_transfer(
u16(buffer.len()).unwrap(),
unsafe { &(*$USARTX::ptr()).dr as *const _ as usize as u32 },
buffer.as_ptr() as u32
);
} }
Transfer::r(buffer, tx_stream, self)
Transfer::w(buffer, rx_stream, self)
} }
} }
)+ )+
} }
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment