@@ -259,14 +259,20 @@ impl I2S {
259
259
_ => Channels :: Right ,
260
260
}
261
261
}
262
+
262
263
/// Receives data into the given `buffer` until it's filled.
264
+ /// Buffer address must be 4 byte aligned and located in RAM.
263
265
/// Returns a value that represents the in-progress DMA transfer.
264
266
#[ allow( unused_mut) ]
265
267
pub fn rx < W , B > ( mut self , mut buffer : B ) -> Result < Transfer < B > , Error >
266
268
where
269
+ W : SupportedWordSize ,
267
270
B : WriteBuffer < Word = W > ,
268
271
{
269
272
let ( ptr, len) = unsafe { buffer. write_buffer ( ) } ;
273
+ if ptr as u32 % 4 != 0 {
274
+ return Err ( Error :: BufferMisaligned ) ;
275
+ }
270
276
let maxcnt = ( len / ( core:: mem:: size_of :: < u32 > ( ) / core:: mem:: size_of :: < W > ( ) ) ) as u32 ;
271
277
if maxcnt > MAX_DMA_MAXCNT {
272
278
return Err ( Error :: BufferTooLong ) ;
@@ -283,7 +289,8 @@ impl I2S {
283
289
284
290
/// Full duplex DMA transfer.
285
291
/// Transmits the given `tx_buffer` while simultaneously receiving data
286
- /// into the given `rx_buffer` until it is filled. The buffers must be of equal size.
292
+ /// into the given `rx_buffer` until it is filled.
293
+ /// The buffers must be of equal size and their addresses must be 4 byte aligned and located in RAM.
287
294
/// Returns a value that represents the in-progress DMA transfer.
288
295
#[ allow( unused_mut) ]
289
296
pub fn transfer < W , TxB , RxB > (
@@ -292,11 +299,15 @@ impl I2S {
292
299
mut rx_buffer : RxB ,
293
300
) -> Result < TransferFullDuplex < TxB , RxB > , Error >
294
301
where
302
+ W : SupportedWordSize ,
295
303
TxB : ReadBuffer < Word = W > ,
296
304
RxB : WriteBuffer < Word = W > ,
297
305
{
298
306
let ( rx_ptr, rx_len) = unsafe { rx_buffer. write_buffer ( ) } ;
299
307
let ( tx_ptr, tx_len) = unsafe { tx_buffer. read_buffer ( ) } ;
308
+ if tx_ptr as u32 % 4 != 0 || rx_ptr as u32 % 4 != 0 {
309
+ return Err ( Error :: BufferMisaligned ) ;
310
+ }
300
311
let maxcnt = ( tx_len / ( core:: mem:: size_of :: < u32 > ( ) / core:: mem:: size_of :: < W > ( ) ) ) as u32 ;
301
312
if tx_len != rx_len {
302
313
return Err ( Error :: BuffersDontMatch ) ;
@@ -328,13 +339,18 @@ impl I2S {
328
339
}
329
340
330
341
/// Transmits the given `tx_buffer`.
342
+ /// Buffer address must be 4 byte aligned and located in RAM.
331
343
/// Returns a value that represents the in-progress DMA transfer.
332
344
#[ allow( unused_mut) ]
333
345
pub fn tx < W , B > ( mut self , buffer : B ) -> Result < Transfer < B > , Error >
334
346
where
347
+ W : SupportedWordSize ,
335
348
B : ReadBuffer < Word = W > ,
336
349
{
337
350
let ( ptr, len) = unsafe { buffer. read_buffer ( ) } ;
351
+ if ptr as u32 % 4 != 0 {
352
+ return Err ( Error :: BufferMisaligned ) ;
353
+ }
338
354
let maxcnt = ( len / ( core:: mem:: size_of :: < u32 > ( ) / core:: mem:: size_of :: < W > ( ) ) ) as u32 ;
339
355
if maxcnt > MAX_DMA_MAXCNT {
340
356
return Err ( Error :: BufferTooLong ) ;
@@ -468,6 +484,7 @@ pub enum Error {
468
484
DMABufferNotInDataMemory ,
469
485
BufferTooLong ,
470
486
BuffersDontMatch ,
487
+ BufferMisaligned ,
471
488
}
472
489
473
490
/// I2S Mode
@@ -650,3 +667,22 @@ impl<TxB, RxB> Drop for TransferFullDuplex<TxB, RxB> {
650
667
}
651
668
}
652
669
}
670
+
671
+ pub trait SupportedWordSize : private:: Sealed { }
672
+ impl private:: Sealed for i8 { }
673
+ impl SupportedWordSize for i8 { }
674
+ impl private:: Sealed for u8 { }
675
+ impl SupportedWordSize for u8 { }
676
+ impl private:: Sealed for i16 { }
677
+ impl SupportedWordSize for i16 { }
678
+ impl private:: Sealed for u16 { }
679
+ impl SupportedWordSize for u16 { }
680
+ impl private:: Sealed for i32 { }
681
+ impl SupportedWordSize for i32 { }
682
+ impl private:: Sealed for u32 { }
683
+ impl SupportedWordSize for u32 { }
684
+
685
+ mod private {
686
+ /// Prevents code outside of the parent module from implementing traits.
687
+ pub trait Sealed { }
688
+ }
0 commit comments