From f7307745e54be4874a15722586bf2e4821f012a3 Mon Sep 17 00:00:00 2001 From: Thales Fragoso Date: Wed, 7 Oct 2020 14:29:41 -0300 Subject: [PATCH] Update docs on DMA code --- src/adc.rs | 67 ++++++++++++++++++++++++------------------------- src/dma.rs | 10 ++++++++ src/serial.rs | 69 +++++++++++++++++++++++---------------------------- src/spi.rs | 21 ++++++++-------- 4 files changed, 83 insertions(+), 84 deletions(-) diff --git a/src/adc.rs b/src/adc.rs index 724c9999..a0f3384a 100644 --- a/src/adc.rs +++ b/src/adc.rs @@ -706,32 +706,30 @@ where B: 'static, { fn circ_read(mut self, mut buffer: &'static mut [B; 2]) -> CircBuffer { - { - // NOTE(unsafe) We own the buffer now and we won't call other `&mut` on it - // until the end of the transfer. - let (ptr, len) = unsafe { buffer.static_write_buffer() }; - self.channel - .set_peripheral_address(unsafe { &(*ADC1::ptr()).dr as *const _ as u32 }, false); - self.channel.set_memory_address(ptr as u32, true); - self.channel.set_transfer_length(len); - - atomic::compiler_fence(Ordering::Release); - - self.channel.ch().cr.modify(|_, w| { - w.mem2mem() - .clear_bit() - .pl() - .medium() - .msize() - .bits16() - .psize() - .bits16() - .circ() - .set_bit() - .dir() - .clear_bit() - }); - } + // NOTE(unsafe) We own the buffer now and we won't call other `&mut` on it + // until the end of the transfer. + let (ptr, len) = unsafe { buffer.static_write_buffer() }; + self.channel + .set_peripheral_address(unsafe { &(*ADC1::ptr()).dr as *const _ as u32 }, false); + self.channel.set_memory_address(ptr as u32, true); + self.channel.set_transfer_length(len); + + atomic::compiler_fence(Ordering::Release); + + self.channel.ch().cr.modify(|_, w| { + w.mem2mem() + .clear_bit() + .pl() + .medium() + .msize() + .bits16() + .psize() + .bits16() + .circ() + .set_bit() + .dir() + .clear_bit() + }); self.start(); @@ -745,15 +743,14 @@ where B: StaticWriteBuffer, { fn read(mut self, mut buffer: B) -> Transfer { - { - // NOTE(unsafe) We own the buffer now and we won't call other `&mut` on it - // until the end of the transfer. - let (ptr, len) = unsafe { buffer.static_write_buffer() }; - self.channel - .set_peripheral_address(unsafe { &(*ADC1::ptr()).dr as *const _ as u32 }, false); - self.channel.set_memory_address(ptr as u32, true); - self.channel.set_transfer_length(len); - } + // NOTE(unsafe) We own the buffer now and we won't call other `&mut` on it + // until the end of the transfer. + let (ptr, len) = unsafe { buffer.static_write_buffer() }; + self.channel + .set_peripheral_address(unsafe { &(*ADC1::ptr()).dr as *const _ as u32 }, false); + self.channel.set_memory_address(ptr as u32, true); + self.channel.set_transfer_length(len); + atomic::compiler_fence(Ordering::Release); self.channel.ch().cr.modify(|_, w| { w.mem2mem() diff --git a/src/dma.rs b/src/dma.rs index 18463611..b999fc28 100644 --- a/src/dma.rs +++ b/src/dma.rs @@ -317,6 +317,11 @@ macro_rules! dma { // we need a fence here for the same reason we need one in `Transfer.wait` atomic::compiler_fence(Ordering::Acquire); + // `Transfer` needs to have a `Drop` implementation, because we accept + // managed buffers that can free their memory on drop. Because of that + // we can't move out of the `Transfer`'s fields, so we use `ptr::read` + // and `mem::forget`. + // // NOTE(unsafe) There is no panic branch between getting the resources // and forgetting `self`. unsafe { @@ -350,6 +355,11 @@ macro_rules! dma { // we need a fence here for the same reason we need one in `Transfer.wait` atomic::compiler_fence(Ordering::Acquire); + // `Transfer` needs to have a `Drop` implementation, because we accept + // managed buffers that can free their memory on drop. Because of that + // we can't move out of the `Transfer`'s fields, so we use `ptr::read` + // and `mem::forget`. + // // NOTE(unsafe) There is no panic branch between getting the resources // and forgetting `self`. unsafe { diff --git a/src/serial.rs b/src/serial.rs index 4a3ce49d..31c16365 100644 --- a/src/serial.rs +++ b/src/serial.rs @@ -590,28 +590,24 @@ macro_rules! serialdma { &'static mut [B; 2]: StaticWriteBuffer, B: 'static, { - fn circ_read(mut self, mut buffer: &'static mut [B; 2], - ) -> CircBuffer - { - { - // NOTE(unsafe) We own the buffer now and we won't call other `&mut` on it - // until the end of the transfer. - let (ptr, len) = unsafe { buffer.static_write_buffer() }; - self.channel.set_peripheral_address(unsafe{ &(*$USARTX::ptr()).dr as *const _ as u32 }, false); - self.channel.set_memory_address(ptr as u32, true); - self.channel.set_transfer_length(len); - - atomic::compiler_fence(Ordering::Release); - - self.channel.ch().cr.modify(|_, w| { w - .mem2mem() .clear_bit() - .pl() .medium() - .msize() .bits8() - .psize() .bits8() - .circ() .set_bit() - .dir() .clear_bit() - }); - } + fn circ_read(mut self, mut buffer: &'static mut [B; 2]) -> CircBuffer { + // NOTE(unsafe) We own the buffer now and we won't call other `&mut` on it + // until the end of the transfer. + let (ptr, len) = unsafe { buffer.static_write_buffer() }; + self.channel.set_peripheral_address(unsafe{ &(*$USARTX::ptr()).dr as *const _ as u32 }, false); + self.channel.set_memory_address(ptr as u32, true); + self.channel.set_transfer_length(len); + + atomic::compiler_fence(Ordering::Release); + + self.channel.ch().cr.modify(|_, w| { w + .mem2mem() .clear_bit() + .pl() .medium() + .msize() .bits8() + .psize() .bits8() + .circ() .set_bit() + .dir() .clear_bit() + }); self.start(); @@ -624,14 +620,13 @@ macro_rules! serialdma { B: StaticWriteBuffer, { fn read(mut self, mut buffer: B) -> Transfer { - { - // NOTE(unsafe) We own the buffer now and we won't call other `&mut` on it - // until the end of the transfer. - let (ptr, len) = unsafe { buffer.static_write_buffer() }; - self.channel.set_peripheral_address(unsafe{ &(*$USARTX::ptr()).dr as *const _ as u32 }, false); - self.channel.set_memory_address(ptr as u32, true); - self.channel.set_transfer_length(len); - } + // NOTE(unsafe) We own the buffer now and we won't call other `&mut` on it + // until the end of the transfer. + let (ptr, len) = unsafe { buffer.static_write_buffer() }; + self.channel.set_peripheral_address(unsafe{ &(*$USARTX::ptr()).dr as *const _ as u32 }, false); + self.channel.set_memory_address(ptr as u32, true); + self.channel.set_transfer_length(len); + atomic::compiler_fence(Ordering::Release); self.channel.ch().cr.modify(|_, w| { w .mem2mem() .clear_bit() @@ -652,16 +647,14 @@ macro_rules! serialdma { B: StaticReadBuffer, { fn write(mut self, buffer: B) -> Transfer { - { - // NOTE(unsafe) We own the buffer now and we won't call other `&mut` on it - // until the end of the transfer. - let (ptr, len) = unsafe { buffer.static_read_buffer() }; + // NOTE(unsafe) We own the buffer now and we won't call other `&mut` on it + // until the end of the transfer. + let (ptr, len) = unsafe { buffer.static_read_buffer() }; - self.channel.set_peripheral_address(unsafe{ &(*$USARTX::ptr()).dr as *const _ as u32 }, false); + self.channel.set_peripheral_address(unsafe{ &(*$USARTX::ptr()).dr as *const _ as u32 }, false); - self.channel.set_memory_address(ptr as u32, true); - self.channel.set_transfer_length(len); - } + self.channel.set_memory_address(ptr as u32, true); + self.channel.set_transfer_length(len); atomic::compiler_fence(Ordering::Release); diff --git a/src/spi.rs b/src/spi.rs index 6a5162b2..931dc4a8 100644 --- a/src/spi.rs +++ b/src/spi.rs @@ -542,17 +542,16 @@ macro_rules! spi_dma { B: StaticReadBuffer, { fn write(mut self, buffer: B) -> Transfer { - { - // NOTE(unsafe) We own the buffer now and we won't call other `&mut` on it - // until the end of the transfer. - let (ptr, len) = unsafe { buffer.static_read_buffer() }; - self.channel.set_peripheral_address( - unsafe { &(*$SPIi::ptr()).dr as *const _ as u32 }, - false, - ); - self.channel.set_memory_address(ptr as u32, true); - self.channel.set_transfer_length(len); - } + // NOTE(unsafe) We own the buffer now and we won't call other `&mut` on it + // until the end of the transfer. + let (ptr, len) = unsafe { buffer.static_read_buffer() }; + self.channel.set_peripheral_address( + unsafe { &(*$SPIi::ptr()).dr as *const _ as u32 }, + false, + ); + self.channel.set_memory_address(ptr as u32, true); + self.channel.set_transfer_length(len); + atomic::compiler_fence(Ordering::Release); self.channel.ch().cr.modify(|_, w| { w