Skip to content

Commit 86560ee

Browse files
committed
Add DMA module
1 parent 414625f commit 86560ee

File tree

15 files changed

+570
-136
lines changed

15 files changed

+570
-136
lines changed

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,12 @@
4949
cortex-m = "0.7"
5050
cortex-m-rt = "0.7"
5151
critical-section = "1.2"
52+
embedded-dma = "0.2"
5253
embedded-hal = "1.0"
5354
embedded-hal-nb = "1.0"
5455
embedded-io = "0.6"
5556
fugit = "0.3"
56-
fugit-timer = "0.1.3"
57+
fugit-timer = "0.1"
5758
nb = "1.1"
5859
rtic-monotonic = { version = "1.0", optional = true }
5960
rtrb = { version = "0.3", default-features = false }

examples/f103c8/src/main.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,9 @@ fn main() -> ! {
9393
&all_it::USART1_CB,
9494
);
9595

96+
let dma1 = dp.DMA1.split(&mut mcu.rcc);
97+
let dma_rx = dma1.5;
98+
9699
// LED --------------------------------------
97100

98101
let mut led = gpiob

scripts/base.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,22 @@ def red(s: str) -> str:
88

99
def blue(s: str) -> str:
1010
return f"\033[1;34m{s}\033[0m"
11+
12+
13+
class Write:
14+
def __init__(self, file_name: str, dry_run: bool = False) -> None:
15+
if dry_run:
16+
self.f = None
17+
else:
18+
self.f = open(file_name, "w", encoding="utf-8")
19+
20+
def write(self, content: str) -> None:
21+
if self.f:
22+
self.f.write(content)
23+
else:
24+
print(content, end="")
25+
26+
def close(self) -> None:
27+
if self.f:
28+
self.f.close()
29+
self.f = None

scripts/generate_dma_table.py

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import csv
2+
import os
3+
import pprint
4+
import subprocess
5+
6+
from base import Write
7+
8+
SCRIPT = os.path.relpath(__file__, os.getcwd()).replace("\\", "/")
9+
10+
11+
def match_filter(filter: str, name: str) -> bool:
12+
if filter == "UART":
13+
return name.startswith("UART") or name.startswith("USART")
14+
return name.startswith(filter)
15+
16+
17+
FUNC_TABLE = {
18+
"TX": "Tx",
19+
"RX": "Rx",
20+
}
21+
22+
23+
TEMPLATE = """
24+
impl DmaBind{func}<pac::{peri}> for {dma}::{ch} {{}}"""
25+
26+
27+
def write_item(dma: str, ch: str, func: str, w: Write) -> None:
28+
ch = ch.replace("ch", "C")
29+
(peri, func) = func.split("_", 1)
30+
func = FUNC_TABLE.get(func, "")
31+
w.write(TEMPLATE.format(func=func, peri=peri, dma=dma, ch=ch))
32+
33+
34+
def write_table(d: dict, filter: str, w: Write) -> None:
35+
for dma, ch_table in sorted(d.items()):
36+
for ch, func_list in sorted(ch_table.items()):
37+
for func in sorted(func_list):
38+
if match_filter(filter, func):
39+
write_item(dma, ch, func, w)
40+
41+
42+
def parse_dma_info(row: list[str], ret_d: dict) -> None:
43+
dma = row[0]
44+
channel = row[1]
45+
func_list: list[str] = []
46+
for func in row[2:]:
47+
if func:
48+
func_list.append(func)
49+
50+
p = ret_d.setdefault(dma, {})
51+
p[channel] = func_list
52+
53+
54+
def csv_to_code(csv_file: str, show: bool = False) -> None:
55+
print(csv_file)
56+
d: dict = {}
57+
with open(csv_file, newline="", encoding="utf-8") as f:
58+
reader = csv.reader(f, delimiter=",", quotechar='"')
59+
for row in reader:
60+
if row[0]:
61+
parse_dma_info(row, d)
62+
63+
if show:
64+
pprint.pprint(d)
65+
66+
target_file = "src/dma.rs"
67+
with open(target_file, "r", encoding="utf-8") as f:
68+
code = f.read()
69+
i = code.find("// table") + len("// table")
70+
before = code[:i]
71+
code = code[i:]
72+
73+
w = Write(target_file)
74+
w.write(before)
75+
w.write("\n// Do NOT manually modify the code.\n")
76+
w.write(
77+
f"// It's generated by {SCRIPT} from {csv_file}\n",
78+
)
79+
80+
write_table(d, "UART", w)
81+
82+
w.close()
83+
subprocess.run(["rustfmt", target_file])
84+
85+
86+
if __name__ == "__main__":
87+
csv_to_code("scripts/table/stm32f1_dma_table.csv")

scripts/generate_remap_table.py

Lines changed: 3 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
import os
33
import pprint
44
import subprocess
5-
from io import TextIOWrapper
5+
6+
from base import Write
67

78
DRY_RUN = False
89
SCRIPT = os.path.relpath(__file__, os.getcwd()).replace("\\", "/")
@@ -34,25 +35,6 @@
3435
}
3536

3637

37-
class Write:
38-
def __init__(self, file_name: str) -> None:
39-
if DRY_RUN:
40-
self.f = None
41-
else:
42-
self.f = open(file_name, "w", encoding="utf-8")
43-
44-
def write(self, content: str) -> None:
45-
if self.f:
46-
self.f.write(content)
47-
else:
48-
print(content, end="")
49-
50-
def close(self) -> None:
51-
if self.f:
52-
self.f.close()
53-
self.f = None
54-
55-
5638
def match_filter(filter: str, name: str) -> bool:
5739
if filter == "UART":
5840
return name.startswith("UART") or name.startswith("USART")
@@ -149,7 +131,7 @@ def write_table(d: dict, filter: str, csv_file: str, target_file: str) -> None:
149131
before = code[:i]
150132
code = code[i:]
151133

152-
w = Write(target_file)
134+
w = Write(target_file, DRY_RUN)
153135
w.write(before)
154136
w.write("\n// Do NOT manually modify the code.\n")
155137
w.write(

src/common/dma/mod.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
pub trait DmaChannel {
2+
fn start(&mut self);
3+
fn stop(&mut self);
4+
5+
fn set_peripheral_address<T: Sized>(
6+
&mut self,
7+
address: usize,
8+
mem_to_periph: bool,
9+
increase: bool,
10+
circular: bool,
11+
);
12+
fn set_memory_address(&mut self, address: usize, increase: bool);
13+
fn set_transfer_length(&mut self, len: usize);
14+
fn set_memory_buf_for_peripheral<T: Sized>(&mut self, buf: &[T]) {
15+
self.set_memory_address(buf.as_ptr() as usize, true);
16+
self.set_transfer_length(buf.len());
17+
}
18+
19+
fn set_memory_to_memory<T: Sized>(&mut self, src_addr: usize, dst_addr: usize, len: usize);
20+
21+
fn get_left_len(&self) -> usize;
22+
fn in_progress(&self) -> bool;
23+
24+
fn set_interrupt(&mut self, event: DmaEvent, enable: bool);
25+
fn is_interrupted(&mut self, event: DmaEvent) -> bool;
26+
}
27+
28+
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
29+
pub enum DmaEvent {
30+
TransferComplete,
31+
HalfTransfer,
32+
}

src/common/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
pub mod dma;
12
pub mod ringbuf;
23
pub mod simplest_heap;
34
pub mod timer;

src/common/uart/mod.rs

Lines changed: 7 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -1,107 +1,20 @@
1-
use crate::ringbuf::{Consumer, Producer, RingBuffer};
2-
use embedded_hal_nb as e_nb;
3-
use embedded_io as e_io;
4-
1+
mod uart_dma_ringbuf_rx;
2+
pub use uart_dma_ringbuf_rx::*;
53
mod uart_it;
4+
pub use uart_it::*;
65
mod uart_poll;
6+
pub use uart_poll::*;
7+
8+
use embedded_hal_nb as e_nb;
9+
use embedded_io as e_io;
710

811
pub use core::convert::Infallible;
9-
pub use uart_it::*;
10-
pub use uart_poll::*;
1112

1213
// pub mod uart_dma_tx;
1314
// pub use uart_dma_tx::*;
14-
// pub mod uart_dma_ringbuf_rx;
15-
// pub use uart_dma_ringbuf_rx::*;
1615
// pub mod uart_dma_ringbuf_tx;
1716
// pub use uart_dma_ringbuf_tx::*;
1817

19-
/// UART Transmitter
20-
pub struct Tx<U> {
21-
uart: [U; 2],
22-
}
23-
24-
impl<U: UartPeriph> Tx<U> {
25-
pub(crate) fn new(uart: [U; 2]) -> Self {
26-
Self { uart }
27-
}
28-
29-
// pub fn get_interrupt_handler(&self) -> UartInterrupt<U> {
30-
// UartInterrupt::new(unsafe { self.uart.steal_mut() })
31-
// }
32-
33-
pub fn into_poll(self, retry_times: u32, flush_retry_times: u32) -> UartPollTx<U> {
34-
let [uart, _] = self.uart;
35-
UartPollTx::<U>::new(uart, retry_times, flush_retry_times)
36-
}
37-
38-
pub fn into_interrupt(
39-
self,
40-
buf_size: usize,
41-
transmit_retry_times: u32,
42-
flush_retry_times: u32,
43-
) -> (UartInterruptTx<U>, UartInterruptTxHandler<U>) {
44-
let (w, r) = RingBuffer::<u8>::new(buf_size);
45-
let [u1, u2] = self.uart;
46-
(
47-
UartInterruptTx::new(u1, w, transmit_retry_times, flush_retry_times),
48-
UartInterruptTxHandler::new(u2, r),
49-
)
50-
}
51-
52-
// pub fn into_dma<CH>(self, dma_ch: CH) -> UartDmaTx<U, CH>
53-
// where
54-
// CH: BindDmaTx<U>,
55-
// {
56-
// UartDmaTx::<U, CH>::new(self.uart, dma_ch)
57-
// }
58-
59-
// pub fn into_dma_ringbuf<CH>(self, dma_ch: CH, buf_size: usize) -> UartDmaBufTx<U, CH>
60-
// where
61-
// CH: BindDmaTx<U>,
62-
// {
63-
// UartDmaBufTx::<U, CH>::new(self.uart, dma_ch, buf_size)
64-
// }
65-
}
66-
67-
// ------------------------------------------------------------------------------------------------
68-
69-
/// UART Receiver
70-
pub struct Rx<U: UartPeriph> {
71-
uart: [U; 2],
72-
}
73-
74-
impl<U: UartPeriph> Rx<U> {
75-
pub(crate) fn new(uart: [U; 2]) -> Self {
76-
Self { uart }
77-
}
78-
79-
pub fn into_poll(self, retry_times: u32, continue_retry_times: u32) -> UartPollRx<U> {
80-
let [uart, _] = self.uart;
81-
UartPollRx::<U>::new(uart, retry_times, continue_retry_times)
82-
}
83-
84-
pub fn into_interrupt(
85-
self,
86-
buf_size: usize,
87-
retry_times: u32,
88-
) -> (UartInterruptRx<U>, UartInterruptRxHandler<U>) {
89-
let (w, r) = RingBuffer::<u8>::new(buf_size);
90-
let [u1, u2] = self.uart;
91-
(
92-
UartInterruptRx::new(u1, r, retry_times),
93-
UartInterruptRxHandler::new(u2, w),
94-
)
95-
}
96-
97-
// pub fn into_dma_circle<CH>(self, dma_ch: CH, buf_size: usize) -> UartDmaBufRx<U, CH>
98-
// where
99-
// CH: BindDmaRx<U>,
100-
// {
101-
// UartDmaBufRx::<U, CH>::new(self.uart, dma_ch, buf_size)
102-
// }
103-
}
104-
10518
// ------------------------------------------------------------------------------------------------
10619

10720
// UART idle interrupt handler

0 commit comments

Comments
 (0)