diff options
| author | JuliDi <[email protected]> | 2023-06-17 11:48:21 +0200 |
|---|---|---|
| committer | JuliDi <[email protected]> | 2023-06-17 11:48:21 +0200 |
| commit | f5d084552d9f44d24f020269cc605de0fb4d1041 (patch) | |
| tree | e7574b0f9e0b20402a330e3e8013ab749c0c9cfe | |
| parent | ec36225f8ab35fab149971e587ef506aa1c9d1ca (diff) | |
implement mwe of a DMA write() method for DAC
| -rw-r--r-- | embassy-stm32/build.rs | 2 | ||||
| -rw-r--r-- | embassy-stm32/src/dac/mod.rs (renamed from embassy-stm32/src/dac.rs) | 76 |
2 files changed, 71 insertions, 7 deletions
diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index 9e597f187..e2bd01d7b 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs | |||
| @@ -699,6 +699,8 @@ fn main() { | |||
| 699 | // SDMMCv1 uses the same channel for both directions, so just implement for RX | 699 | // SDMMCv1 uses the same channel for both directions, so just implement for RX |
| 700 | (("sdmmc", "RX"), quote!(crate::sdmmc::SdmmcDma)), | 700 | (("sdmmc", "RX"), quote!(crate::sdmmc::SdmmcDma)), |
| 701 | (("quadspi", "QUADSPI"), quote!(crate::qspi::QuadDma)), | 701 | (("quadspi", "QUADSPI"), quote!(crate::qspi::QuadDma)), |
| 702 | (("dac", "CH1"), quote!(crate::dac::Dma)), | ||
| 703 | (("dac", "CH2"), quote!(crate::dac::Dma)), | ||
| 702 | ] | 704 | ] |
| 703 | .into(); | 705 | .into(); |
| 704 | 706 | ||
diff --git a/embassy-stm32/src/dac.rs b/embassy-stm32/src/dac/mod.rs index 60e856c78..348d8bccd 100644 --- a/embassy-stm32/src/dac.rs +++ b/embassy-stm32/src/dac/mod.rs | |||
| @@ -2,6 +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::{slice_ptr_parts, word, Transfer}; | ||
| 5 | use crate::pac::dac; | 6 | use crate::pac::dac; |
| 6 | use crate::rcc::RccPeripheral; | 7 | use crate::rcc::RccPeripheral; |
| 7 | use crate::{peripherals, Peripheral}; | 8 | use crate::{peripherals, Peripheral}; |
| @@ -97,39 +98,58 @@ pub enum Value { | |||
| 97 | Bit12(u16, Alignment), | 98 | Bit12(u16, Alignment), |
| 98 | } | 99 | } |
| 99 | 100 | ||
| 100 | pub struct Dac<'d, T: Instance> { | 101 | pub struct Dac<'d, T: Instance, Tx> { |
| 101 | channels: u8, | 102 | channels: u8, |
| 103 | txdma: PeripheralRef<'d, Tx>, | ||
| 102 | _peri: PeripheralRef<'d, T>, | 104 | _peri: PeripheralRef<'d, T>, |
| 103 | } | 105 | } |
| 104 | 106 | ||
| 105 | impl<'d, T: Instance> Dac<'d, T> { | 107 | impl<'d, T: Instance, Tx> Dac<'d, T, Tx> { |
| 106 | pub fn new_1ch(peri: impl Peripheral<P = T> + 'd, _ch1: impl Peripheral<P = impl DacPin<T, 1>> + 'd) -> Self { | 108 | pub fn new_1ch( |
| 109 | peri: impl Peripheral<P = T> + 'd, | ||
| 110 | txdma: impl Peripheral<P = Tx> + 'd, | ||
| 111 | _ch1: impl Peripheral<P = impl DacPin<T, 1>> + 'd, | ||
| 112 | ) -> Self { | ||
| 107 | into_ref!(peri); | 113 | into_ref!(peri); |
| 108 | Self::new_inner(peri, 1) | 114 | Self::new_inner(peri, 1, txdma) |
| 109 | } | 115 | } |
| 110 | 116 | ||
| 111 | pub fn new_2ch( | 117 | pub fn new_2ch( |
| 112 | peri: impl Peripheral<P = T> + 'd, | 118 | peri: impl Peripheral<P = T> + 'd, |
| 119 | txdma: impl Peripheral<P = Tx> + 'd, | ||
| 113 | _ch1: impl Peripheral<P = impl DacPin<T, 1>> + 'd, | 120 | _ch1: impl Peripheral<P = impl DacPin<T, 1>> + 'd, |
| 114 | _ch2: impl Peripheral<P = impl DacPin<T, 2>> + 'd, | 121 | _ch2: impl Peripheral<P = impl DacPin<T, 2>> + 'd, |
| 115 | ) -> Self { | 122 | ) -> Self { |
| 116 | into_ref!(peri); | 123 | into_ref!(peri); |
| 117 | Self::new_inner(peri, 2) | 124 | Self::new_inner(peri, 2, txdma) |
| 118 | } | 125 | } |
| 119 | 126 | ||
| 120 | fn new_inner(peri: PeripheralRef<'d, T>, channels: u8) -> Self { | 127 | fn new_inner(peri: PeripheralRef<'d, T>, channels: u8, txdma: impl Peripheral<P = Tx> + 'd) -> Self { |
| 128 | into_ref!(txdma); | ||
| 121 | T::enable(); | 129 | T::enable(); |
| 122 | T::reset(); | 130 | T::reset(); |
| 123 | 131 | ||
| 124 | unsafe { | 132 | unsafe { |
| 133 | T::regs().mcr().modify(|reg| { | ||
| 134 | for ch in 0..channels { | ||
| 135 | reg.set_mode(ch as usize, 0); | ||
| 136 | reg.set_mode(ch as usize, 0); | ||
| 137 | } | ||
| 138 | }); | ||
| 139 | |||
| 125 | T::regs().cr().modify(|reg| { | 140 | T::regs().cr().modify(|reg| { |
| 126 | for ch in 0..channels { | 141 | for ch in 0..channels { |
| 127 | reg.set_en(ch as usize, true); | 142 | reg.set_en(ch as usize, true); |
| 143 | reg.set_ten(ch as usize, true); | ||
| 128 | } | 144 | } |
| 129 | }); | 145 | }); |
| 130 | } | 146 | } |
| 131 | 147 | ||
| 132 | Self { channels, _peri: peri } | 148 | Self { |
| 149 | channels, | ||
| 150 | txdma, | ||
| 151 | _peri: peri, | ||
| 152 | } | ||
| 133 | } | 153 | } |
| 134 | 154 | ||
| 135 | /// Check the channel is configured | 155 | /// Check the channel is configured |
| @@ -215,6 +235,47 @@ impl<'d, T: Instance> Dac<'d, T> { | |||
| 215 | } | 235 | } |
| 216 | Ok(()) | 236 | Ok(()) |
| 217 | } | 237 | } |
| 238 | |||
| 239 | /// TODO: Allow an array of Value instead of only u16, right-aligned | ||
| 240 | pub async fn write(&mut self, data: &[u16]) -> Result<(), Error> | ||
| 241 | where | ||
| 242 | Tx: Dma<T>, | ||
| 243 | { | ||
| 244 | // TODO: Make this a parameter or get it from the struct or so... | ||
| 245 | const CHANNEL: usize = 0; | ||
| 246 | |||
| 247 | //debug!("Starting DAC"); | ||
| 248 | unsafe { | ||
| 249 | T::regs().cr().modify(|w| { | ||
| 250 | w.set_en(CHANNEL, true); | ||
| 251 | w.set_dmaen(CHANNEL, true); | ||
| 252 | }); | ||
| 253 | } | ||
| 254 | |||
| 255 | let tx_request = self.txdma.request(); | ||
| 256 | |||
| 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; | ||
| 259 | |||
| 260 | let tx_f = unsafe { Transfer::new_write(&mut self.txdma, tx_request, data, tx_dst, Default::default()) }; | ||
| 261 | |||
| 262 | //debug!("Awaiting tx_f"); | ||
| 263 | |||
| 264 | tx_f.await; | ||
| 265 | |||
| 266 | // finish dma | ||
| 267 | unsafe { | ||
| 268 | // TODO: Do we need to check any status registers here? | ||
| 269 | |||
| 270 | T::regs().cr().modify(|w| { | ||
| 271 | // Disable the dac peripheral | ||
| 272 | //w.set_en(CHANNEL, false); | ||
| 273 | // Disable the DMA. TODO: Is this necessary? | ||
| 274 | //w.set_dmaen(CHANNEL, false); | ||
| 275 | }); | ||
| 276 | } | ||
| 277 | Ok(()) | ||
| 278 | } | ||
| 218 | } | 279 | } |
| 219 | 280 | ||
| 220 | pub(crate) mod sealed { | 281 | pub(crate) mod sealed { |
| @@ -224,6 +285,7 @@ pub(crate) mod sealed { | |||
| 224 | } | 285 | } |
| 225 | 286 | ||
| 226 | pub trait Instance: sealed::Instance + RccPeripheral + 'static {} | 287 | pub trait Instance: sealed::Instance + RccPeripheral + 'static {} |
| 288 | dma_trait!(Dma, Instance); | ||
| 227 | 289 | ||
| 228 | pub trait DacPin<T: Instance, const C: u8>: crate::gpio::Pin + 'static {} | 290 | pub trait DacPin<T: Instance, const C: u8>: crate::gpio::Pin + 'static {} |
| 229 | 291 | ||
