record&restore TIM OC to it's earlier state
This commit is contained in:
		
							parent
							
								
									8c2a6df03b
								
							
						
					
					
						commit
						24f569821c
					
				| @ -99,6 +99,11 @@ pub(crate) mod sealed { | |||||||
|             Self::regs().dier().modify(|r| r.set_ude(enable)); |             Self::regs().dier().modify(|r| r.set_ude(enable)); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         /// Get the update dma enable/disable state.
 | ||||||
|  |         fn get_update_dma_state(&self) -> bool { | ||||||
|  |             Self::regs().dier().read().ude() | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         /// Enable/disable autoreload preload.
 |         /// Enable/disable autoreload preload.
 | ||||||
|         fn set_autoreload_preload(&mut self, enable: bool) { |         fn set_autoreload_preload(&mut self, enable: bool) { | ||||||
|             Self::regs().cr1().modify(|r| r.set_arpe(enable)); |             Self::regs().cr1().modify(|r| r.set_arpe(enable)); | ||||||
| @ -274,6 +279,11 @@ pub(crate) mod sealed { | |||||||
|             Self::regs_gp16().ccer().modify(|w| w.set_cce(channel.index(), enable)); |             Self::regs_gp16().ccer().modify(|w| w.set_cce(channel.index(), enable)); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         /// Get enable/disable state of a channel
 | ||||||
|  |         fn get_channel_enable_state(&self, channel: Channel) -> bool { | ||||||
|  |             Self::regs_gp16().ccer().read().cce(channel.index()) | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         /// Set compare value for a channel.
 |         /// Set compare value for a channel.
 | ||||||
|         fn set_compare_value(&mut self, channel: Channel, value: u16) { |         fn set_compare_value(&mut self, channel: Channel, value: u16) { | ||||||
|             Self::regs_gp16().ccr(channel.index()).modify(|w| w.set_ccr(value)); |             Self::regs_gp16().ccr(channel.index()).modify(|w| w.set_ccr(value)); | ||||||
|  | |||||||
| @ -62,6 +62,12 @@ pub struct SimplePwm<'d, T, Dma> { | |||||||
| 
 | 
 | ||||||
| impl<'d, T: CaptureCompare16bitInstance, Dma> SimplePwm<'d, T, Dma> { | impl<'d, T: CaptureCompare16bitInstance, Dma> SimplePwm<'d, T, Dma> { | ||||||
|     /// Create a new simple PWM driver.
 |     /// Create a new simple PWM driver.
 | ||||||
|  |     ///
 | ||||||
|  |     /// Note:  
 | ||||||
|  |     /// If you want to use [`Self::gen_waveform()`], you need to provide corresponding TIMx_UP DMA channel.
 | ||||||
|  |     /// Otherwise you can just put a [`dma::NoDma`](crate::dma::NoDma)  
 | ||||||
|  |     /// Currently, you can only use one channel at a time to generate waveform with [`Self::gen_waveform()`].  
 | ||||||
|  |     /// But you can always use multiple TIM to generate multiple waveform simultaneously.
 | ||||||
|     pub fn new( |     pub fn new( | ||||||
|         tim: impl Peripheral<P = T> + 'd, |         tim: impl Peripheral<P = T> + 'd, | ||||||
|         _ch1: Option<PwmPin<'d, T, Ch1>>, |         _ch1: Option<PwmPin<'d, T, Ch1>>, | ||||||
| @ -113,6 +119,11 @@ impl<'d, T: CaptureCompare16bitInstance, Dma> SimplePwm<'d, T, Dma> { | |||||||
|         self.inner.enable_channel(channel, false); |         self.inner.enable_channel(channel, false); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     /// Check whether given channel is enabled
 | ||||||
|  |     pub fn is_enabled(&self, channel: Channel) -> bool { | ||||||
|  |         self.inner.get_channel_enable_state(channel) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     /// Set PWM frequency.
 |     /// Set PWM frequency.
 | ||||||
|     ///
 |     ///
 | ||||||
|     /// Note: when you call this, the max duty value changes, so you will have to
 |     /// Note: when you call this, the max duty value changes, so you will have to
 | ||||||
| @ -141,6 +152,13 @@ impl<'d, T: CaptureCompare16bitInstance, Dma> SimplePwm<'d, T, Dma> { | |||||||
|         self.inner.set_compare_value(channel, duty) |         self.inner.set_compare_value(channel, duty) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     /// Get the duty for a given channel.
 | ||||||
|  |     ///
 | ||||||
|  |     /// The value ranges from 0 for 0% duty, to [`get_max_duty`](Self::get_max_duty) for 100% duty, both included.
 | ||||||
|  |     pub fn get_duty(&self, channel: Channel) -> u16 { | ||||||
|  |         self.inner.get_compare_value(channel) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     /// Set the output polarity for a given channel.
 |     /// Set the output polarity for a given channel.
 | ||||||
|     pub fn set_polarity(&mut self, channel: Channel, polarity: OutputPolarity) { |     pub fn set_polarity(&mut self, channel: Channel, polarity: OutputPolarity) { | ||||||
|         self.inner.set_output_polarity(channel, polarity); |         self.inner.set_output_polarity(channel, polarity); | ||||||
| @ -153,26 +171,38 @@ where | |||||||
| { | { | ||||||
|     /// Generate a sequence of PWM waveform
 |     /// Generate a sequence of PWM waveform
 | ||||||
|     pub async fn gen_waveform(&mut self, channel: Channel, duty: &[u16]) { |     pub async fn gen_waveform(&mut self, channel: Channel, duty: &[u16]) { | ||||||
|         duty.iter().all(|v| v.le(&self.get_max_duty())); |         assert!(duty.iter().all(|v| *v <= self.get_max_duty())); | ||||||
| 
 |  | ||||||
|         self.inner.enable_update_dma(true); |  | ||||||
| 
 | 
 | ||||||
|         #[cfg_attr(any(stm32f334, stm32f378), allow(clippy::let_unit_value))] |         #[cfg_attr(any(stm32f334, stm32f378), allow(clippy::let_unit_value))] | ||||||
|         let req = self.dma.request(); |         let req = self.dma.request(); | ||||||
| 
 | 
 | ||||||
|         self.enable(channel); |  | ||||||
| 
 |  | ||||||
|         #[cfg(not(any(bdma, gpdma)))] |         #[cfg(not(any(bdma, gpdma)))] | ||||||
|         let dma_regs = self.dma.regs(); |         let dma_regs = self.dma.regs(); | ||||||
|         #[cfg(not(any(bdma, gpdma)))] |         #[cfg(not(any(bdma, gpdma)))] | ||||||
|         let isr_num = self.dma.num() / 4; |         let isr_num = self.dma.num() / 4; | ||||||
|         #[cfg(not(any(bdma, gpdma)))] |         #[cfg(not(any(bdma, gpdma)))] | ||||||
|         let isr_bit = self.dma.num() % 4; |         let isr_bit = self.dma.num() % 4; | ||||||
|  |         #[cfg(not(any(bdma, gpdma)))] | ||||||
|  |         let isr_reg = dma_regs.isr(isr_num); | ||||||
|  |         #[cfg(not(any(bdma, gpdma)))] | ||||||
|  |         let ifcr_reg = dma_regs.ifcr(isr_num); | ||||||
| 
 | 
 | ||||||
|         #[cfg(not(any(bdma, gpdma)))] |         #[cfg(not(any(bdma, gpdma)))] | ||||||
|         // clean DMA FIFO error before a transfer
 |         // clean DMA FIFO error before a transfer
 | ||||||
|         if dma_regs.isr(isr_num).read().feif(isr_bit) { |         if isr_reg.read().feif(isr_bit) { | ||||||
|             dma_regs.ifcr(isr_num).write(|v| v.set_feif(isr_bit, true)); |             ifcr_reg.write(|v| v.set_feif(isr_bit, true)); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         let original_duty_state = self.get_duty(channel); | ||||||
|  |         let original_enable_state = self.is_enabled(channel); | ||||||
|  |         let original_update_dma_state = self.inner.get_update_dma_state(); | ||||||
|  | 
 | ||||||
|  |         if !original_update_dma_state { | ||||||
|  |             self.inner.enable_update_dma(true); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if !original_enable_state { | ||||||
|  |             self.enable(channel); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         unsafe { |         unsafe { | ||||||
| @ -198,15 +228,20 @@ where | |||||||
|             .await |             .await | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|  |         // restore output compare state
 | ||||||
|  |         if !original_enable_state { | ||||||
|             self.disable(channel); |             self.disable(channel); | ||||||
| 
 |         } | ||||||
|  |         self.set_duty(channel, original_duty_state); | ||||||
|  |         if !original_update_dma_state { | ||||||
|             self.inner.enable_update_dma(false); |             self.inner.enable_update_dma(false); | ||||||
| 
 | 
 | ||||||
|             #[cfg(not(any(bdma, gpdma)))] |             #[cfg(not(any(bdma, gpdma)))] | ||||||
|         // Since DMA is closed before timer update event trigger DMA is turn off, it will almost always trigger a DMA FIFO error.
 |             // Since DMA could be closed before timer update event trigger DMA is turn off, this can almost always trigger a DMA FIFO error.
 | ||||||
|         // Thus, we will always clean DMA FEIF after each transfer
 |             // Thus, we will try clean DMA FEIF after each transfer
 | ||||||
|         if dma_regs.isr(isr_num).read().feif(isr_bit) { |             if isr_reg.read().feif(isr_bit) { | ||||||
|             dma_regs.ifcr(isr_num).write(|v| v.set_feif(isr_bit, true)); |                 ifcr_reg.write(|v| v.set_feif(isr_bit, true)); | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user