diff options
| author | JuliDi <[email protected]> | 2023-06-18 18:51:36 +0200 |
|---|---|---|
| committer | JuliDi <[email protected]> | 2023-06-18 18:51:36 +0200 |
| commit | f8ee33abb9943d6fe57c126eeecb36db9935c4ba (patch) | |
| tree | 8764043bc2cd73527a0a013eac0e889010f564ab | |
| parent | 78a2ca8a0e5af3fe2c76a6cd025b74ea4322f6cf (diff) | |
add half transfer interrupt and circular dma
| -rw-r--r-- | embassy-stm32/src/dac/mod.rs | 17 | ||||
| -rw-r--r-- | embassy-stm32/src/dma/bdma.rs | 26 |
2 files changed, 36 insertions, 7 deletions
diff --git a/embassy-stm32/src/dac/mod.rs b/embassy-stm32/src/dac/mod.rs index 7b81ec1f2..525d45d72 100644 --- a/embassy-stm32/src/dac/mod.rs +++ b/embassy-stm32/src/dac/mod.rs | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | 2 | ||
| 3 | use embassy_hal_common::{into_ref, PeripheralRef}; | 3 | use embassy_hal_common::{into_ref, PeripheralRef}; |
| 4 | 4 | ||
| 5 | use crate::dma::Transfer; | 5 | use crate::dma::{Transfer, TransferOptions}; |
| 6 | use crate::pac::dac; | 6 | use crate::pac::dac; |
| 7 | use crate::rcc::RccPeripheral; | 7 | use crate::rcc::RccPeripheral; |
| 8 | use crate::{peripherals, Peripheral}; | 8 | use crate::{peripherals, Peripheral}; |
| @@ -237,7 +237,7 @@ impl<'d, T: Instance, Tx> Dac<'d, T, Tx> { | |||
| 237 | } | 237 | } |
| 238 | 238 | ||
| 239 | /// TODO: Allow an array of Value instead of only u16, right-aligned | 239 | /// TODO: Allow an array of Value instead of only u16, right-aligned |
| 240 | pub async fn write(&mut self, data: &[u16]) -> Result<(), Error> | 240 | pub async fn write(&mut self, data: &[u16], circular: bool) -> Result<(), Error> |
| 241 | where | 241 | where |
| 242 | Tx: Dma<T>, | 242 | Tx: Dma<T>, |
| 243 | { | 243 | { |
| @@ -257,7 +257,18 @@ impl<'d, T: Instance, Tx> Dac<'d, T, Tx> { | |||
| 257 | // Use the 12 bit right-aligned register for now. TODO: distinguish values | 257 | // Use the 12 bit right-aligned register for now. TODO: distinguish values |
| 258 | let tx_dst = T::regs().dhr12r(CHANNEL).ptr() as *mut u16; | 258 | let tx_dst = T::regs().dhr12r(CHANNEL).ptr() as *mut u16; |
| 259 | 259 | ||
| 260 | let tx_f = unsafe { Transfer::new_write(&mut self.txdma, tx_request, data, tx_dst, Default::default()) }; | 260 | let tx_f = unsafe { |
| 261 | Transfer::new_write( | ||
| 262 | &mut self.txdma, | ||
| 263 | tx_request, | ||
| 264 | data, | ||
| 265 | tx_dst, | ||
| 266 | TransferOptions { | ||
| 267 | circular, | ||
| 268 | halt_transfer_ir: false, | ||
| 269 | }, | ||
| 270 | ) | ||
| 271 | }; | ||
| 261 | 272 | ||
| 262 | //debug!("Awaiting tx_f"); | 273 | //debug!("Awaiting tx_f"); |
| 263 | 274 | ||
diff --git a/embassy-stm32/src/dma/bdma.rs b/embassy-stm32/src/dma/bdma.rs index c0a503e25..ca18047e7 100644 --- a/embassy-stm32/src/dma/bdma.rs +++ b/embassy-stm32/src/dma/bdma.rs | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | #![macro_use] | 1 | #![macro_use] |
| 2 | 2 | ||
| 3 | use core::future::Future; | 3 | use core::future::Future; |
| 4 | use core::option; | ||
| 4 | use core::pin::Pin; | 5 | use core::pin::Pin; |
| 5 | use core::sync::atomic::{fence, Ordering}; | 6 | use core::sync::atomic::{fence, Ordering}; |
| 6 | use core::task::{Context, Poll, Waker}; | 7 | use core::task::{Context, Poll, Waker}; |
| @@ -21,11 +22,17 @@ use crate::pac::bdma::{regs, vals}; | |||
| 21 | #[derive(Debug, Copy, Clone, PartialEq, Eq)] | 22 | #[derive(Debug, Copy, Clone, PartialEq, Eq)] |
| 22 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 23 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 23 | #[non_exhaustive] | 24 | #[non_exhaustive] |
| 24 | pub struct TransferOptions {} | 25 | pub struct TransferOptions { |
| 26 | pub circular: bool, | ||
| 27 | pub halt_transfer_ir: bool, | ||
| 28 | } | ||
| 25 | 29 | ||
| 26 | impl Default for TransferOptions { | 30 | impl Default for TransferOptions { |
| 27 | fn default() -> Self { | 31 | fn default() -> Self { |
| 28 | Self {} | 32 | Self { |
| 33 | circular: false, | ||
| 34 | halt_transfer_ir: false, | ||
| 35 | } | ||
| 29 | } | 36 | } |
| 30 | } | 37 | } |
| 31 | 38 | ||
| @@ -253,7 +260,7 @@ impl<'a, C: Channel> Transfer<'a, C> { | |||
| 253 | mem_len: usize, | 260 | mem_len: usize, |
| 254 | incr_mem: bool, | 261 | incr_mem: bool, |
| 255 | data_size: WordSize, | 262 | data_size: WordSize, |
| 256 | _options: TransferOptions, | 263 | options: TransferOptions, |
| 257 | ) -> Self { | 264 | ) -> Self { |
| 258 | let ch = channel.regs().ch(channel.num()); | 265 | let ch = channel.regs().ch(channel.num()); |
| 259 | 266 | ||
| @@ -284,6 +291,14 @@ impl<'a, C: Channel> Transfer<'a, C> { | |||
| 284 | w.set_dir(dir.into()); | 291 | w.set_dir(dir.into()); |
| 285 | w.set_teie(true); | 292 | w.set_teie(true); |
| 286 | w.set_tcie(true); | 293 | w.set_tcie(true); |
| 294 | w.set_htie(options.halt_transfer_ir); | ||
| 295 | if options.circular { | ||
| 296 | w.set_circ(vals::Circ::ENABLED); | ||
| 297 | debug!("Setting circular mode"); | ||
| 298 | } else { | ||
| 299 | w.set_circ(vals::Circ::DISABLED); | ||
| 300 | } | ||
| 301 | w.set_pl(vals::Pl::VERYHIGH); | ||
| 287 | w.set_en(true); | 302 | w.set_en(true); |
| 288 | }); | 303 | }); |
| 289 | 304 | ||
| @@ -314,8 +329,9 @@ impl<'a, C: Channel> Transfer<'a, C> { | |||
| 314 | pub fn is_running(&mut self) -> bool { | 329 | pub fn is_running(&mut self) -> bool { |
| 315 | let ch = self.channel.regs().ch(self.channel.num()); | 330 | let ch = self.channel.regs().ch(self.channel.num()); |
| 316 | let en = unsafe { ch.cr().read() }.en(); | 331 | let en = unsafe { ch.cr().read() }.en(); |
| 332 | let circular = unsafe { ch.cr().read() }.circ() == vals::Circ::ENABLED; | ||
| 317 | let tcif = STATE.complete_count[self.channel.index()].load(Ordering::Acquire) != 0; | 333 | let tcif = STATE.complete_count[self.channel.index()].load(Ordering::Acquire) != 0; |
| 318 | en && !tcif | 334 | en && (circular || !tcif) |
| 319 | } | 335 | } |
| 320 | 336 | ||
| 321 | /// Gets the total remaining transfers for the channel | 337 | /// Gets the total remaining transfers for the channel |
| @@ -482,6 +498,8 @@ impl<'a, C: Channel, W: Word> RingBuffer<'a, C, W> { | |||
| 482 | let ch = self.channel.regs().ch(self.channel.num()); | 498 | let ch = self.channel.regs().ch(self.channel.num()); |
| 483 | 499 | ||
| 484 | // Disable the channel. Keep the IEs enabled so the irqs still fire. | 500 | // Disable the channel. Keep the IEs enabled so the irqs still fire. |
| 501 | // If the channel is enabled and transfer is not completed, we need to perform | ||
| 502 | // two separate write access to the CR register to disable the channel. | ||
| 485 | unsafe { | 503 | unsafe { |
| 486 | ch.cr().write(|w| { | 504 | ch.cr().write(|w| { |
| 487 | w.set_teie(true); | 505 | w.set_teie(true); |
