140
140
//!
141
141
//! HALs **must not** add infrastructure for sharing at the [`SpiBus`] level. User code owning a [`SpiBus`] must have the guarantee
142
142
//! of exclusive access.
143
+ //!
144
+ //! # Flushing
145
+ //!
146
+ //! To improve performance, [`SpiBus`] implementations are allowed to return before the operation is finished, i.e. when the bus is still not
147
+ //! idle.
148
+ //!
149
+ //! When using a [`SpiBus`], call [`flush`](SpiBusFlush::flush) to wait for operations to actually finish. Examples of situations
150
+ //! where this is needed are:
151
+ //! - To synchronize SPI activity and GPIO activity, for example before deasserting a CS pin.
152
+ //! - Before deinitializing the hardware SPI peripheral.
153
+ //!
154
+ //! When using a [`SpiDevice`], you can still call [`flush`](SpiBusFlush::flush) on the bus within a transaction.
155
+ //! It's very rarely needed, because [`transaction`](SpiDevice::transaction) already flushes for you
156
+ //! before deasserting CS. For example, you may need it to synchronize with GPIOs other than CS, such as DCX pins
157
+ //! sometimes found in SPI displays.
158
+ //!
159
+ //! For example, for [`write`](SpiBusWrite::write) operations, it is common for hardware SPI peripherals to have a small
160
+ //! FIFO buffer, usually 1-4 bytes. Software writes data to the FIFO, and the peripheral sends it on MOSI at its own pace,
161
+ //! at the specified SPI frequency. It is allowed for an implementation of [`write`](SpiBusWrite::write) to return as soon
162
+ //! as all the data has been written to the FIFO, before it is actually sent. Calling [`flush`](SpiBusFlush::flush) would
163
+ //! wait until all the bits have actually been sent, the FIFO is empty, and the bus is idle.
164
+ //!
165
+ //! This still applies to other operations such as [`read`](SpiBusRead::read) or [`transfer`](SpiBus::transfer). It is less obvious
166
+ //! why, because these methods can't return before receiving all the read data. However it's still technically possible
167
+ //! for them to return before the bus is idle. For example, assuming SPI mode 0, the last bit is sampled on the first (rising) edge
168
+ //! of SCK, at which point a method could return, but the second (falling) SCK edge still has to happen before the bus is idle.
143
169
144
170
use core:: fmt:: Debug ;
145
171
@@ -162,6 +188,7 @@ pub trait SpiDevice: ErrorType {
162
188
/// - Locks the bus
163
189
/// - Asserts the CS (Chip Select) pin.
164
190
/// - Calls `f` with an exclusive reference to the bus, which can then be used to do transfers against the device.
191
+ /// - [Flushes](SpiBusFlush::flush) the bus.
165
192
/// - Deasserts the CS pin.
166
193
/// - Unlocks the bus.
167
194
///
@@ -236,12 +263,29 @@ impl<T: SpiDevice> SpiDevice for &mut T {
236
263
}
237
264
}
238
265
266
+ /// Flush support for SPI bus
267
+ pub trait SpiBusFlush : ErrorType {
268
+ /// Blocks until all operations have completed and the bus is idle.
269
+ ///
270
+ /// See the [module-level documentation](self) for important usage information.
271
+ fn flush ( & mut self ) -> Result < ( ) , Self :: Error > ;
272
+ }
273
+
274
+ impl < T : SpiBusFlush > SpiBusFlush for & mut T {
275
+ fn flush ( & mut self ) -> Result < ( ) , Self :: Error > {
276
+ T :: flush ( self )
277
+ }
278
+ }
279
+
239
280
/// Read-only SPI bus
240
- pub trait SpiBusRead < Word : Copy = u8 > : ErrorType {
281
+ pub trait SpiBusRead < Word : Copy = u8 > : SpiBusFlush {
241
282
/// Reads `words` from the slave.
242
283
///
243
284
/// The word value sent on MOSI during reading is implementation-defined,
244
285
/// typically `0x00`, `0xFF`, or configurable.
286
+ ///
287
+ /// Implementations are allowed to return before the operation is
288
+ /// complete. See the [module-level documentation](self) for detials.
245
289
fn read ( & mut self , words : & mut [ Word ] ) -> Result < ( ) , Self :: Error > ;
246
290
}
247
291
@@ -252,8 +296,11 @@ impl<T: SpiBusRead<Word>, Word: Copy> SpiBusRead<Word> for &mut T {
252
296
}
253
297
254
298
/// Write-only SPI bus
255
- pub trait SpiBusWrite < Word : Copy = u8 > : ErrorType {
299
+ pub trait SpiBusWrite < Word : Copy = u8 > : SpiBusFlush {
256
300
/// Writes `words` to the slave, ignoring all the incoming words
301
+ ///
302
+ /// Implementations are allowed to return before the operation is
303
+ /// complete. See the [module-level documentation](self) for detials.
257
304
fn write ( & mut self , words : & [ Word ] ) -> Result < ( ) , Self :: Error > ;
258
305
}
259
306
@@ -277,11 +324,17 @@ pub trait SpiBus<Word: Copy = u8>: SpiBusRead<Word> + SpiBusWrite<Word> {
277
324
/// incoming words after `read` has been filled will be discarded. If `write` is shorter,
278
325
/// the value of words sent in MOSI after all `write` has been sent is implementation-defined,
279
326
/// typically `0x00`, `0xFF`, or configurable.
327
+ ///
328
+ /// Implementations are allowed to return before the operation is
329
+ /// complete. See the [module-level documentation](self) for detials.
280
330
fn transfer ( & mut self , read : & mut [ Word ] , write : & [ Word ] ) -> Result < ( ) , Self :: Error > ;
281
331
282
332
/// Writes and reads simultaneously. The contents of `words` are
283
333
/// written to the slave, and the received words are stored into the same
284
334
/// `words` buffer, overwriting it.
335
+ ///
336
+ /// Implementations are allowed to return before the operation is
337
+ /// complete. See the [module-level documentation](self) for detials.
285
338
fn transfer_in_place ( & mut self , words : & mut [ Word ] ) -> Result < ( ) , Self :: Error > ;
286
339
}
287
340
@@ -335,15 +388,15 @@ impl<BUS, CS> ExclusiveDevice<BUS, CS> {
335
388
336
389
impl < BUS , CS > ErrorType for ExclusiveDevice < BUS , CS >
337
390
where
338
- BUS : ErrorType ,
391
+ BUS : SpiBusFlush ,
339
392
CS : OutputPin ,
340
393
{
341
394
type Error = ExclusiveDeviceError < BUS :: Error , CS :: Error > ;
342
395
}
343
396
344
397
impl < BUS , CS > SpiDevice for ExclusiveDevice < BUS , CS >
345
398
where
346
- BUS : ErrorType ,
399
+ BUS : SpiBusFlush ,
347
400
CS : OutputPin ,
348
401
{
349
402
type Bus = BUS ;
@@ -356,10 +409,12 @@ where
356
409
357
410
let f_res = f ( & mut self . bus ) ;
358
411
359
- // If the closure fails, it's important to still deassert CS.
412
+ // On failure, it's important to still flush and deassert CS.
413
+ let flush_res = self . bus . flush ( ) ;
360
414
let cs_res = self . cs . set_high ( ) ;
361
415
362
416
let f_res = f_res. map_err ( ExclusiveDeviceError :: Spi ) ?;
417
+ flush_res. map_err ( ExclusiveDeviceError :: Spi ) ?;
363
418
cs_res. map_err ( ExclusiveDeviceError :: Cs ) ?;
364
419
365
420
Ok ( f_res)
0 commit comments