@@ -259,14 +259,20 @@ impl I2S {
259259 _ => Channels :: Right ,
260260 }
261261 }
262+
262263 /// Receives data into the given `buffer` until it's filled.
264+ /// Buffer address must be 4 byte aligned and located in RAM.
263265 /// Returns a value that represents the in-progress DMA transfer.
264266 #[ allow( unused_mut) ]
265267 pub fn rx < W , B > ( mut self , mut buffer : B ) -> Result < Transfer < B > , Error >
266268 where
269+ W : SupportedWordSize ,
267270 B : WriteBuffer < Word = W > ,
268271 {
269272 let ( ptr, len) = unsafe { buffer. write_buffer ( ) } ;
273+ if ptr as u32 % 4 != 0 {
274+ return Err ( Error :: BufferMisaligned ) ;
275+ }
270276 let maxcnt = ( len / ( core:: mem:: size_of :: < u32 > ( ) / core:: mem:: size_of :: < W > ( ) ) ) as u32 ;
271277 if maxcnt > MAX_DMA_MAXCNT {
272278 return Err ( Error :: BufferTooLong ) ;
@@ -283,7 +289,8 @@ impl I2S {
283289
284290 /// Full duplex DMA transfer.
285291 /// 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.
287294 /// Returns a value that represents the in-progress DMA transfer.
288295 #[ allow( unused_mut) ]
289296 pub fn transfer < W , TxB , RxB > (
@@ -292,11 +299,15 @@ impl I2S {
292299 mut rx_buffer : RxB ,
293300 ) -> Result < TransferFullDuplex < TxB , RxB > , Error >
294301 where
302+ W : SupportedWordSize ,
295303 TxB : ReadBuffer < Word = W > ,
296304 RxB : WriteBuffer < Word = W > ,
297305 {
298306 let ( rx_ptr, rx_len) = unsafe { rx_buffer. write_buffer ( ) } ;
299307 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+ }
300311 let maxcnt = ( tx_len / ( core:: mem:: size_of :: < u32 > ( ) / core:: mem:: size_of :: < W > ( ) ) ) as u32 ;
301312 if tx_len != rx_len {
302313 return Err ( Error :: BuffersDontMatch ) ;
@@ -328,13 +339,18 @@ impl I2S {
328339 }
329340
330341 /// Transmits the given `tx_buffer`.
342+ /// Buffer address must be 4 byte aligned and located in RAM.
331343 /// Returns a value that represents the in-progress DMA transfer.
332344 #[ allow( unused_mut) ]
333345 pub fn tx < W , B > ( mut self , buffer : B ) -> Result < Transfer < B > , Error >
334346 where
347+ W : SupportedWordSize ,
335348 B : ReadBuffer < Word = W > ,
336349 {
337350 let ( ptr, len) = unsafe { buffer. read_buffer ( ) } ;
351+ if ptr as u32 % 4 != 0 {
352+ return Err ( Error :: BufferMisaligned ) ;
353+ }
338354 let maxcnt = ( len / ( core:: mem:: size_of :: < u32 > ( ) / core:: mem:: size_of :: < W > ( ) ) ) as u32 ;
339355 if maxcnt > MAX_DMA_MAXCNT {
340356 return Err ( Error :: BufferTooLong ) ;
@@ -468,6 +484,7 @@ pub enum Error {
468484 DMABufferNotInDataMemory ,
469485 BufferTooLong ,
470486 BuffersDontMatch ,
487+ BufferMisaligned ,
471488}
472489
473490/// I2S Mode
@@ -650,3 +667,22 @@ impl<TxB, RxB> Drop for TransferFullDuplex<TxB, RxB> {
650667 }
651668 }
652669}
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