diff options
| author | elagil <[email protected]> | 2024-11-16 15:02:32 +0100 |
|---|---|---|
| committer | elagil <[email protected]> | 2024-11-16 15:02:32 +0100 |
| commit | d592875ca6d4df2b126e67603d32ed7f3e71910b (patch) | |
| tree | 04a86d83160817fa4f06f63a5cdb85886f320636 /embassy-stm32/src | |
| parent | 6c4b3d82b637fce5ab6efdc312d7852381d8ddeb (diff) | |
fix(SAI): disallow start without initial write
Diffstat (limited to 'embassy-stm32/src')
| -rw-r--r-- | embassy-stm32/src/dma/dma_bdma.rs | 3 | ||||
| -rw-r--r-- | embassy-stm32/src/sai/mod.rs | 27 |
2 files changed, 14 insertions, 16 deletions
diff --git a/embassy-stm32/src/dma/dma_bdma.rs b/embassy-stm32/src/dma/dma_bdma.rs index cdc603e2c..08c7a5508 100644 --- a/embassy-stm32/src/dma/dma_bdma.rs +++ b/embassy-stm32/src/dma/dma_bdma.rs | |||
| @@ -828,7 +828,6 @@ impl<'a, W: Word> ReadableRingBuffer<'a, W> { | |||
| 828 | /// You must call this after creating it for it to work. | 828 | /// You must call this after creating it for it to work. |
| 829 | pub fn start(&mut self) { | 829 | pub fn start(&mut self) { |
| 830 | self.channel.start(); | 830 | self.channel.start(); |
| 831 | self.clear(); | ||
| 832 | } | 831 | } |
| 833 | 832 | ||
| 834 | /// Clear all data in the ring buffer. | 833 | /// Clear all data in the ring buffer. |
| @@ -981,7 +980,6 @@ impl<'a, W: Word> WritableRingBuffer<'a, W> { | |||
| 981 | /// You must call this after creating it for it to work. | 980 | /// You must call this after creating it for it to work. |
| 982 | pub fn start(&mut self) { | 981 | pub fn start(&mut self) { |
| 983 | self.channel.start(); | 982 | self.channel.start(); |
| 984 | self.clear(); | ||
| 985 | } | 983 | } |
| 986 | 984 | ||
| 987 | /// Clear all data in the ring buffer. | 985 | /// Clear all data in the ring buffer. |
| @@ -991,7 +989,6 @@ impl<'a, W: Word> WritableRingBuffer<'a, W> { | |||
| 991 | 989 | ||
| 992 | /// Write elements directly to the raw buffer. | 990 | /// Write elements directly to the raw buffer. |
| 993 | /// This can be used to fill the buffer before starting the DMA transfer. | 991 | /// This can be used to fill the buffer before starting the DMA transfer. |
| 994 | #[allow(dead_code)] | ||
| 995 | pub fn write_immediate(&mut self, buf: &[W]) -> Result<(usize, usize), Error> { | 992 | pub fn write_immediate(&mut self, buf: &[W]) -> Result<(usize, usize), Error> { |
| 996 | self.ringbuf.write_immediate(buf) | 993 | self.ringbuf.write_immediate(buf) |
| 997 | } | 994 | } |
diff --git a/embassy-stm32/src/sai/mod.rs b/embassy-stm32/src/sai/mod.rs index 62b44b77f..057b21980 100644 --- a/embassy-stm32/src/sai/mod.rs +++ b/embassy-stm32/src/sai/mod.rs | |||
| @@ -958,13 +958,14 @@ impl<'d, T: Instance, W: word::Word> Sai<'d, T, W> { | |||
| 958 | } | 958 | } |
| 959 | 959 | ||
| 960 | /// Start the SAI driver. | 960 | /// Start the SAI driver. |
| 961 | pub fn start(&mut self) { | 961 | /// |
| 962 | /// Only receivers can be started. Transmitters are started on the first writing operation. | ||
| 963 | pub fn start(&mut self) -> Result<(), Error> { | ||
| 962 | match self.ring_buffer { | 964 | match self.ring_buffer { |
| 963 | RingBuffer::Writable(ref mut rb) => { | 965 | RingBuffer::Writable(_) => Err(Error::NotAReceiver), |
| 964 | rb.start(); | ||
| 965 | } | ||
| 966 | RingBuffer::Readable(ref mut rb) => { | 966 | RingBuffer::Readable(ref mut rb) => { |
| 967 | rb.start(); | 967 | rb.start(); |
| 968 | Ok(()) | ||
| 968 | } | 969 | } |
| 969 | } | 970 | } |
| 970 | } | 971 | } |
| @@ -981,14 +982,6 @@ impl<'d, T: Instance, W: word::Word> Sai<'d, T, W> { | |||
| 981 | rcc::enable_and_reset::<T>(); | 982 | rcc::enable_and_reset::<T>(); |
| 982 | } | 983 | } |
| 983 | 984 | ||
| 984 | /// Flush. | ||
| 985 | pub fn flush(&mut self) { | ||
| 986 | let ch = T::REGS.ch(self.sub_block as usize); | ||
| 987 | ch.cr1().modify(|w| w.set_saien(false)); | ||
| 988 | ch.cr2().modify(|w| w.set_fflush(true)); | ||
| 989 | ch.cr1().modify(|w| w.set_saien(true)); | ||
| 990 | } | ||
| 991 | |||
| 992 | /// Enable or disable mute. | 985 | /// Enable or disable mute. |
| 993 | pub fn set_mute(&mut self, value: bool) { | 986 | pub fn set_mute(&mut self, value: bool) { |
| 994 | let ch = T::REGS.ch(self.sub_block as usize); | 987 | let ch = T::REGS.ch(self.sub_block as usize); |
| @@ -1012,6 +1005,9 @@ impl<'d, T: Instance, W: word::Word> Sai<'d, T, W> { | |||
| 1012 | 1005 | ||
| 1013 | /// Write data to the SAI ringbuffer. | 1006 | /// Write data to the SAI ringbuffer. |
| 1014 | /// | 1007 | /// |
| 1008 | /// The first write starts the DMA after filling the ring buffer with the provided data. | ||
| 1009 | /// This ensures that the DMA does not run before data is available in the ring buffer. | ||
| 1010 | /// | ||
| 1015 | /// This appends the data to the buffer and returns immediately. The | 1011 | /// This appends the data to the buffer and returns immediately. The |
| 1016 | /// data will be transmitted in the background. | 1012 | /// data will be transmitted in the background. |
| 1017 | /// | 1013 | /// |
| @@ -1019,7 +1015,12 @@ impl<'d, T: Instance, W: word::Word> Sai<'d, T, W> { | |||
| 1019 | pub async fn write(&mut self, data: &[W]) -> Result<(), Error> { | 1015 | pub async fn write(&mut self, data: &[W]) -> Result<(), Error> { |
| 1020 | match &mut self.ring_buffer { | 1016 | match &mut self.ring_buffer { |
| 1021 | RingBuffer::Writable(buffer) => { | 1017 | RingBuffer::Writable(buffer) => { |
| 1022 | buffer.write_exact(data).await?; | 1018 | if buffer.is_running() { |
| 1019 | buffer.write_exact(data).await?; | ||
| 1020 | } else { | ||
| 1021 | buffer.write_immediate(data)?; | ||
| 1022 | buffer.start(); | ||
| 1023 | } | ||
| 1023 | Ok(()) | 1024 | Ok(()) |
| 1024 | } | 1025 | } |
| 1025 | _ => return Err(Error::NotATransmitter), | 1026 | _ => return Err(Error::NotATransmitter), |
