Updating DACs to utilize DBM

This commit is contained in:
Ryan Summers 2020-12-17 14:27:47 +01:00
parent ec2aaecb48
commit fb1ea765ce
4 changed files with 17 additions and 16 deletions

2
Cargo.lock generated
View File

@ -874,7 +874,7 @@ dependencies = [
[[package]] [[package]]
name = "stm32h7xx-hal" name = "stm32h7xx-hal"
version = "0.8.0" version = "0.8.0"
source = "git+https://github.com/stm32-rs/stm32h7xx-hal?branch=dma#0bfeeca4ce120c1b7c6d140a7da73a4372b874d8" source = "git+https://github.com/quartiq/stm32h7xx-hal?branch=feature/dma-buffer-swap-logic#5f97920b639f8cb29c9f30c89a33960d5b2082f8"
dependencies = [ dependencies = [
"bare-metal 1.0.0", "bare-metal 1.0.0",
"cast", "cast",

View File

@ -56,8 +56,8 @@ default-features = false
[dependencies.stm32h7xx-hal] [dependencies.stm32h7xx-hal]
features = ["stm32h743v", "rt", "unproven", "ethernet", "quadspi"] features = ["stm32h743v", "rt", "unproven", "ethernet", "quadspi"]
git = "https://github.com/stm32-rs/stm32h7xx-hal" git = "https://github.com/quartiq/stm32h7xx-hal"
branch = "dma" branch = "feature/dma-buffer-swap-logic"
[features] [features]
semihosting = ["panic-semihosting", "cortex-m-log/semihosting"] semihosting = ["panic-semihosting", "cortex-m-log/semihosting"]

View File

@ -117,11 +117,11 @@ macro_rules! adc_input {
/// Whenever the DMA request occurs, it should write into SPI's TX FIFO to start a DMA /// Whenever the DMA request occurs, it should write into SPI's TX FIFO to start a DMA
/// transfer. /// transfer.
fn address(&self) -> u32 { fn address(&self) -> usize {
// Note(unsafe): It is assumed that SPI is owned by another DMA transfer and this DMA is // Note(unsafe): It is assumed that SPI is owned by another DMA transfer and this DMA is
// only used for the transmit-half of DMA. // only used for the transmit-half of DMA.
let regs = unsafe { &*hal::stm32::$spi::ptr() }; let regs = unsafe { &*hal::stm32::$spi::ptr() };
&regs.txdr as *const _ as u32 &regs.txdr as *const _ as usize
} }
} }

View File

@ -34,12 +34,11 @@
///! DMA channels to arbitrate which transfer occurs first. ///! DMA channels to arbitrate which transfer occurs first.
///! ///!
///! ///!
///! # Future Improvements ///! # Limitations
///! ///!
///! In this implementation, single buffer mode DMA transfers are used. As a result of this, it's ///! While double-buffered mode is used for DMA to avoid lost DAC-update events, there is no check
///! possible that a timer comparison could be missed during the swap-over, which will result in a ///! for re-use of a previously provided DAC output buffer. It is assumed that the DMA request is
///! delay of a single output code. In the future, this can be remedied by utilize double-buffer ///! served promptly after the transfer completes.
///! mode for the DMA transfers.
use super::{ use super::{
hal, sampling_timer, DMAReq, DmaConfig, MemoryToPeripheral, TargetAddress, hal, sampling_timer, DMAReq, DmaConfig, MemoryToPeripheral, TargetAddress,
Transfer, SAMPLE_BUFFER_SIZE, Transfer, SAMPLE_BUFFER_SIZE,
@ -50,8 +49,8 @@ use super::{
// processed). Note that the contents of AXI SRAM is uninitialized, so the buffer contents on // processed). Note that the contents of AXI SRAM is uninitialized, so the buffer contents on
// startup are undefined. The dimensions are `ADC_BUF[adc_index][ping_pong_index][sample_index]`. // startup are undefined. The dimensions are `ADC_BUF[adc_index][ping_pong_index][sample_index]`.
#[link_section = ".axisram.buffers"] #[link_section = ".axisram.buffers"]
static mut DAC_BUF: [[[u16; SAMPLE_BUFFER_SIZE]; 2]; 2] = static mut DAC_BUF: [[[u16; SAMPLE_BUFFER_SIZE]; 3]; 2] =
[[[0; SAMPLE_BUFFER_SIZE]; 2]; 2]; [[[0; SAMPLE_BUFFER_SIZE]; 3]; 2];
macro_rules! dac_output { macro_rules! dac_output {
($name:ident, $index:literal, $data_stream:ident, ($name:ident, $index:literal, $data_stream:ident,
@ -92,8 +91,8 @@ macro_rules! dac_output {
const REQUEST_LINE: Option<u8> = Some(DMAReq::$dma_req as u8); const REQUEST_LINE: Option<u8> = Some(DMAReq::$dma_req as u8);
/// Whenever the DMA request occurs, it should write into SPI's TX FIFO. /// Whenever the DMA request occurs, it should write into SPI's TX FIFO.
fn address(&self) -> u32 { fn address(&self) -> usize {
&self.spi.inner().txdr as *const _ as u32 &self.spi.inner().txdr as *const _ as usize
} }
} }
@ -129,6 +128,7 @@ macro_rules! dac_output {
// The stream constantly writes to the TX FIFO to write new update codes. // The stream constantly writes to the TX FIFO to write new update codes.
let trigger_config = DmaConfig::default() let trigger_config = DmaConfig::default()
.memory_increment(true) .memory_increment(true)
.double_buffer(true)
.peripheral_increment(false); .peripheral_increment(false);
// Listen for any potential SPI error signals, which may indicate that we are not generating // Listen for any potential SPI error signals, which may indicate that we are not generating
@ -153,7 +153,8 @@ macro_rules! dac_output {
$spi::new(trigger_channel, spi), $spi::new(trigger_channel, spi),
// Note(unsafe): This buffer is only used once and provided for the DMA transfer. // Note(unsafe): This buffer is only used once and provided for the DMA transfer.
unsafe { &mut DAC_BUF[$index][0] }, unsafe { &mut DAC_BUF[$index][0] },
None, // Note(unsafe): This buffer is only used once and provided for the DMA transfer.
unsafe { Some(&mut DAC_BUF[$index][1]) },
trigger_config, trigger_config,
); );
@ -162,7 +163,7 @@ macro_rules! dac_output {
Self { Self {
transfer, transfer,
// Note(unsafe): This buffer is only used once and provided for the next DMA transfer. // Note(unsafe): This buffer is only used once and provided for the next DMA transfer.
next_buffer: unsafe { Some(&mut DAC_BUF[$index][1]) }, next_buffer: unsafe { Some(&mut DAC_BUF[$index][2]) },
} }
} }