Skip to content

Commit 62d26c0

Browse files
committed
Fixes; improvements for starting transactions
1 parent fbec3cc commit 62d26c0

File tree

2 files changed

+98
-68
lines changed

2 files changed

+98
-68
lines changed

src/spi.rs

Lines changed: 41 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -838,22 +838,23 @@ impl<SPI: Instance, W: Word> Spi<SPI, W> {
838838
}
839839

840840
/// Sets up a frame transaction with the given amount of data words.
841-
///
842-
/// If this is called when a transaction has already started,
843-
/// then an error is returned with [Error::TransactionAlreadyStarted].
844841
fn setup_transaction(&mut self, length: usize) {
845842
assert!(
846843
length <= u16::MAX as usize,
847844
"Buffer too big! Max transaction size is {}",
848845
u16::MAX
849846
);
850847

851-
self.set_transfer_word_count(length.get() as u16);
848+
self.inner.set_transfer_word_count(length as u16);
849+
850+
self.start_transaction();
851+
}
852852

853+
fn start_transaction(&mut self) {
853854
// Re-enable
854855
self.inner.clear_modf();
855856
self.inner.enable();
856-
self.spi().cr1().modify(|_, w| w.cstart().started());
857+
self.inner.start_transfer();
857858
}
858859

859860
/// Checks if the current transaction is complete and disables the
@@ -930,14 +931,7 @@ impl<SPI: Instance, W: Word> Spi<SPI, W> {
930931
}
931932
}
932933

933-
fn start_write<'a>(
934-
&mut self,
935-
words: &'a [W],
936-
) -> Result<Transaction<Write<'a, W>, W>, Error> {
937-
assert!(
938-
!words.is_empty(),
939-
"Write buffer should not be non-zero length"
940-
);
934+
fn setup_write_mode(&mut self) -> Result<(), Error> {
941935
let communication_mode = self.inner.communication_mode();
942936
if communication_mode == CommunicationMode::SimplexReceiver {
943937
return Err(Error::InvalidOperation);
@@ -947,16 +941,25 @@ impl<SPI: Instance, W: Word> Spi<SPI, W> {
947941
self.inner.set_dir_transmitter();
948942
}
949943

944+
Ok(())
945+
}
946+
947+
fn start_write<'a>(
948+
&mut self,
949+
words: &'a [W],
950+
) -> Result<Transaction<Write<'a, W>, W>, Error> {
951+
assert!(
952+
!words.is_empty(),
953+
"Write buffer should not be non-zero length"
954+
);
955+
956+
self.setup_write_mode()?;
950957
self.setup_transaction(words.len());
951958

952959
Ok(Transaction::<Write<'a, W>, W>::write(words))
953960
}
954961

955-
fn start_read<'a>(
956-
&mut self,
957-
buf: &'a mut [W],
958-
) -> Result<Transaction<Read<'a, W>, W>, Error> {
959-
assert!(!buf.is_empty(), "Read buffer should not be non-zero length");
962+
fn setup_read_mode(&self) -> Result<(), Error> {
960963
let communication_mode = self.inner.communication_mode();
961964
if communication_mode == CommunicationMode::SimplexTransmitter {
962965
return Err(Error::InvalidOperation);
@@ -966,11 +969,29 @@ impl<SPI: Instance, W: Word> Spi<SPI, W> {
966969
self.inner.set_dir_receiver();
967970
}
968971

972+
Ok(())
973+
}
974+
975+
fn start_read<'a>(
976+
&mut self,
977+
buf: &'a mut [W],
978+
) -> Result<Transaction<Read<'a, W>, W>, Error> {
979+
assert!(!buf.is_empty(), "Read buffer should not be non-zero length");
980+
981+
self.setup_read_mode()?;
969982
self.setup_transaction(buf.len());
970983

971984
Ok(Transaction::<Read<'a, W>, W>::read(buf))
972985
}
973986

987+
fn check_transfer_mode(&mut self) -> Result<(), Error> {
988+
if self.inner.communication_mode() != CommunicationMode::FullDuplex {
989+
Err(Error::InvalidOperation)
990+
} else {
991+
Ok(())
992+
}
993+
}
994+
974995
fn start_transfer<'a>(
975996
&mut self,
976997
read: &'a mut [W],
@@ -980,10 +1001,8 @@ impl<SPI: Instance, W: Word> Spi<SPI, W> {
9801001
!read.is_empty() && !write.is_empty(),
9811002
"Transfer buffers should not be of zero length"
9821003
);
983-
if self.inner.communication_mode() != CommunicationMode::FullDuplex {
984-
return Err(Error::InvalidOperation);
985-
}
9861004

1005+
self.check_transfer_mode()?;
9871006
self.setup_transaction(core::cmp::max(read.len(), write.len()));
9881007

9891008
Ok(Transaction::<Transfer<'a, W>, W>::transfer(write, read))
@@ -997,9 +1016,7 @@ impl<SPI: Instance, W: Word> Spi<SPI, W> {
9971016
!words.is_empty(),
9981017
"Transfer buffer should not be of zero length"
9991018
);
1000-
if self.inner.communication_mode() != CommunicationMode::FullDuplex {
1001-
return Err(Error::InvalidOperation);
1002-
}
1019+
self.check_transfer_mode()?;
10031020

10041021
self.setup_transaction(words.len());
10051022

src/spi/dma.rs

Lines changed: 57 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
use core::{marker::PhantomData, num::NonZeroUsize};
1+
use core::marker::PhantomData;
22

33
use embedded_dma::{ReadBuffer, WriteBuffer};
44

55
use crate::gpdma::{
66
config::{Config as DmaConfig, MemoryToPeripheral, PeripheralToMemory},
7-
Channel, Transfer as DmaTransfer, Word,
7+
Channel, ChannelRegs, Transfer as DmaTransfer, Word as DmaWord,
88
};
99

10-
use super::{Error, FrameSize, Instance, Spi};
10+
use super::{Error, Instance, Spi, Word};
1111

1212
pub struct DmaRx<SPI, W> {
1313
_spi: PhantomData<SPI>,
@@ -23,7 +23,7 @@ impl<SPI, W> DmaRx<SPI, W> {
2323
}
2424
}
2525

26-
unsafe impl<SPI: Instance, W: FrameSize> ReadBuffer for DmaRx<SPI, W> {
26+
unsafe impl<SPI: Instance, W: Word> ReadBuffer for DmaRx<SPI, W> {
2727
type Word = W;
2828

2929
unsafe fn read_buffer(&self) -> (*const Self::Word, usize) {
@@ -45,27 +45,32 @@ impl<SPI, W> DmaTx<SPI, W> {
4545
}
4646
}
4747

48-
unsafe impl<SPI: Instance, W: FrameSize> WriteBuffer for DmaTx<SPI, W> {
48+
unsafe impl<SPI: Instance, W: Word> WriteBuffer for DmaTx<SPI, W> {
4949
type Word = W;
5050

5151
unsafe fn write_buffer(&mut self) -> (*mut Self::Word, usize) {
5252
((*SPI::ptr()).txdr().as_ptr() as *mut W, 1)
5353
}
5454
}
5555

56-
pub struct RxDmaTransfer<'a, SPI, W: FrameSize, CH, D> {
56+
pub struct RxDmaTransfer<'a, SPI, W: Word, CH, D> {
5757
spi: &'a mut Spi<SPI, W>,
5858
transfer: DmaTransfer<CH, DmaRx<SPI, W>, D, PeripheralToMemory>,
5959
}
6060

6161
impl<'a, SPI, W, CH, D> RxDmaTransfer<'a, SPI, W, CH, D>
6262
where
6363
SPI: Instance,
64-
W: FrameSize + Word,
65-
CH: Channel,
64+
W: Word + DmaWord,
65+
CH: ChannelRegs,
6666
D: WriteBuffer<Word = W>,
6767
{
68-
pub fn new(spi: &'a mut Spi<SPI, W>, channel: CH, destination: D) -> Self {
68+
pub fn new(
69+
spi: &'a mut Spi<SPI, W>,
70+
channel: Channel<CH>,
71+
mut destination: D,
72+
) -> Self {
73+
let (_, len) = unsafe { destination.write_buffer() };
6974
let config = DmaConfig::new().with_request(SPI::rx_dma_request());
7075
let source = DmaRx::new();
7176
let transfer = DmaTransfer::peripheral_to_memory(
@@ -74,15 +79,17 @@ where
7479
source,
7580
destination,
7681
);
82+
spi.inner.set_transfer_word_count(len as u16);
7783
Self { spi, transfer }
7884
}
7985

80-
pub fn start(&mut self) -> Result<(), crate::gpdma::Error> {
81-
self.spi.enable_rx_dma();
86+
pub fn start(&mut self) -> Result<(), Error> {
87+
self.spi.setup_read_mode()?;
88+
self.spi.inner.enable_rx_dma();
8289
self.transfer.start_with(|_, _| {
83-
self.spi.enable();
84-
self.spi.start_transfer();
85-
})
90+
self.spi.start_transaction();
91+
})?;
92+
Ok(())
8693
}
8794

8895
pub fn is_dma_complete(&self) -> Result<bool, Error> {
@@ -93,28 +100,33 @@ where
93100

94101
pub fn end_transfer(&mut self) {
95102
self.spi.end_transaction();
96-
self.spi.disable_dma();
103+
self.spi.inner.disable_dma();
97104
}
98105

99-
pub fn free(self) -> Result<(CH, D), Error> {
106+
pub fn free(self) -> Result<(Channel<CH>, D), Error> {
100107
let (ch, _, d) = self.transfer.free()?;
101108
Ok((ch, d))
102109
}
103110
}
104111

105-
pub struct TxDmaTransfer<'a, SPI, W: FrameSize, CH, S> {
112+
pub struct TxDmaTransfer<'a, SPI, W: Word, CH, S> {
106113
spi: &'a mut Spi<SPI, W>,
107114
transfer: DmaTransfer<CH, S, DmaTx<SPI, W>, MemoryToPeripheral>,
108115
}
109116

110117
impl<'a, SPI, W, CH, S> TxDmaTransfer<'a, SPI, W, CH, S>
111118
where
112119
SPI: Instance,
113-
W: FrameSize + Word,
114-
CH: Channel,
120+
W: DmaWord + Word,
121+
CH: ChannelRegs,
115122
S: ReadBuffer<Word = W>,
116123
{
117-
pub fn new(spi: &'a mut Spi<SPI, W>, channel: CH, source: S) -> Self {
124+
pub fn new(
125+
spi: &'a mut Spi<SPI, W>,
126+
channel: Channel<CH>,
127+
source: S,
128+
) -> Self {
129+
let (_, len) = unsafe { source.read_buffer() };
118130
let config = DmaConfig::new().with_request(SPI::tx_dma_request());
119131
let destination = DmaTx::new();
120132
let transfer = DmaTransfer::memory_to_peripheral(
@@ -123,15 +135,17 @@ where
123135
source,
124136
destination,
125137
);
138+
spi.inner.set_transfer_word_count(len as u16);
126139
Self { spi, transfer }
127140
}
128141

129-
pub fn start(&mut self) -> Result<(), crate::gpdma::Error> {
142+
pub fn start(&mut self) -> Result<(), Error> {
143+
self.spi.setup_write_mode()?;
130144
self.transfer.start_with(|_, _| {
131-
self.spi.enable_tx_dma();
132-
self.spi.enable();
133-
self.spi.start_transfer();
134-
})
145+
self.spi.inner.enable_tx_dma();
146+
self.spi.start_transaction();
147+
})?;
148+
Ok(())
135149
}
136150

137151
pub fn is_dma_complete(&self) -> Result<bool, Error> {
@@ -142,35 +156,34 @@ where
142156

143157
pub fn end_transfer(&mut self) {
144158
self.spi.end_transaction();
145-
self.spi.disable_dma();
159+
self.spi.inner.disable_dma();
146160
}
147161

148-
pub fn free(self) -> Result<(CH, S), Error> {
162+
pub fn free(self) -> Result<(Channel<CH>, S), Error> {
149163
let (ch, s, _) = self.transfer.free()?;
150164
Ok((ch, s))
151165
}
152166
}
153167

154-
pub struct DuplexDmaTransfer<'a, SPI, W: FrameSize, TX, RX, S, D> {
168+
pub struct DuplexDmaTransfer<'a, SPI, W: Word, TX, RX, S, D> {
155169
spi: &'a mut Spi<SPI, W>,
156170
tx_transfer: DmaTransfer<TX, S, DmaTx<SPI, W>, MemoryToPeripheral>,
157171
rx_transfer: DmaTransfer<RX, DmaRx<SPI, W>, D, PeripheralToMemory>,
158-
len: usize,
159172
}
160173

161174
impl<'a, SPI, W, RX, TX, S, D> DuplexDmaTransfer<'a, SPI, W, TX, RX, S, D>
162175
where
163176
SPI: Instance,
164-
W: FrameSize + Word,
165-
TX: Channel,
166-
RX: Channel,
177+
W: Word + DmaWord,
178+
TX: ChannelRegs,
179+
RX: ChannelRegs,
167180
S: ReadBuffer<Word = W>,
168181
D: WriteBuffer<Word = W>,
169182
{
170183
pub fn new(
171184
spi: &'a mut Spi<SPI, W>,
172-
tx_channel: TX,
173-
rx_channel: RX,
185+
tx_channel: Channel<TX>,
186+
rx_channel: Channel<RX>,
174187
source: S,
175188
mut destination: D,
176189
) -> Self {
@@ -192,11 +205,11 @@ where
192205
rx_source,
193206
destination,
194207
);
208+
spi.inner.set_transfer_word_count(dest_len as u16);
195209
Self {
196210
spi,
197211
tx_transfer,
198212
rx_transfer,
199-
len: dest_len,
200213
}
201214
}
202215

@@ -209,12 +222,12 @@ where
209222
}
210223

211224
pub fn start(&mut self) -> Result<(), Error> {
212-
self.spi.enable_rx_dma();
213-
self.rx_transfer.start_nb();
214-
self.tx_transfer.start_nb();
215-
self.spi.enable_tx_dma();
216-
self.spi
217-
.setup_transaction(NonZeroUsize::new(self.len).unwrap())?;
225+
self.spi.check_transfer_mode()?;
226+
self.spi.inner.enable_rx_dma();
227+
self.rx_transfer.start_nonblocking();
228+
self.tx_transfer.start_nonblocking();
229+
self.spi.inner.enable_tx_dma();
230+
self.spi.start_transaction();
218231
Ok(())
219232
}
220233

@@ -228,13 +241,13 @@ where
228241
self.tx_transfer.wait_for_transfer_complete()?;
229242
self.rx_transfer.wait_for_transfer_complete()?;
230243
self.spi.end_transaction();
231-
self.spi.disable_dma();
244+
self.spi.inner.disable_dma();
232245
Ok(())
233246
}
234247

235248
pub fn end_transfer(&mut self) {
236249
self.spi.end_transaction();
237-
self.spi.disable_dma();
250+
self.spi.inner.disable_dma();
238251
}
239252

240253
pub fn abort(&mut self) -> Result<(), Error> {
@@ -244,7 +257,7 @@ where
244257
Ok(())
245258
}
246259

247-
pub fn free(mut self) -> Result<(TX, RX, S, D), Error> {
260+
pub fn free(mut self) -> Result<(Channel<TX>, Channel<RX>, S, D), Error> {
248261
self.end_transfer();
249262
let (tx, s, _) = self.tx_transfer.free()?;
250263
let (rx, _, d) = self.rx_transfer.free()?;

0 commit comments

Comments
 (0)