diff options
| -rw-r--r-- | embassy-stm32/src/adc/g4.rs | 116 |
1 files changed, 60 insertions, 56 deletions
diff --git a/embassy-stm32/src/adc/g4.rs b/embassy-stm32/src/adc/g4.rs index d8aaaba55..613fe921b 100644 --- a/embassy-stm32/src/adc/g4.rs +++ b/embassy-stm32/src/adc/g4.rs | |||
| @@ -429,6 +429,8 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 429 | sequence.len() <= 16, | 429 | sequence.len() <= 16, |
| 430 | "Asynchronous read sequence cannot be more than 16 in length" | 430 | "Asynchronous read sequence cannot be more than 16 in length" |
| 431 | ); | 431 | ); |
| 432 | |||
| 433 | // Ensure no conversions are ongoing and ADC is enabled. | ||
| 432 | Self::cancel_conversions(); | 434 | Self::cancel_conversions(); |
| 433 | self.enable(); | 435 | self.enable(); |
| 434 | 436 | ||
| @@ -523,68 +525,16 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 523 | }) | 525 | }) |
| 524 | } | 526 | } |
| 525 | 527 | ||
| 526 | /// Configure a sequence of injected channels | ||
| 527 | pub fn configure_injected_sequence<'a>( | ||
| 528 | &mut self, | ||
| 529 | sequence: impl ExactSizeIterator<Item = (&'a mut AnyAdcChannel<T>, SampleTime)>, | ||
| 530 | ) { | ||
| 531 | assert!(sequence.len() != 0, "Read sequence cannot be empty"); | ||
| 532 | assert!( | ||
| 533 | sequence.len() <= NR_INJECTED_RANKS, | ||
| 534 | "Read sequence cannot be more than 4 in length" | ||
| 535 | ); | ||
| 536 | |||
| 537 | // Ensure no conversions are ongoing and ADC is enabled. | ||
| 538 | Self::cancel_conversions(); | ||
| 539 | self.enable(); | ||
| 540 | |||
| 541 | // Set sequence length | ||
| 542 | T::regs().jsqr().modify(|w| { | ||
| 543 | w.set_jl(sequence.len() as u8 - 1); | ||
| 544 | }); | ||
| 545 | |||
| 546 | // Configure channels and ranks | ||
| 547 | for (n, (channel, sample_time)) in sequence.enumerate() { | ||
| 548 | Self::configure_channel(channel, sample_time); | ||
| 549 | |||
| 550 | match n { | ||
| 551 | 0..=3 => { | ||
| 552 | T::regs().jsqr().modify(|w| { | ||
| 553 | w.set_jsq(n, channel.channel()); | ||
| 554 | }); | ||
| 555 | } | ||
| 556 | 4..=8 => { | ||
| 557 | T::regs().jsqr().modify(|w| { | ||
| 558 | w.set_jsq(n - 4, channel.channel()); | ||
| 559 | }); | ||
| 560 | } | ||
| 561 | 9..=13 => { | ||
| 562 | T::regs().jsqr().modify(|w| { | ||
| 563 | w.set_jsq(n - 9, channel.channel()); | ||
| 564 | }); | ||
| 565 | } | ||
| 566 | 14..=15 => { | ||
| 567 | T::regs().jsqr().modify(|w| { | ||
| 568 | w.set_jsq(n - 14, channel.channel()); | ||
| 569 | }); | ||
| 570 | } | ||
| 571 | _ => unreachable!(), | ||
| 572 | } | ||
| 573 | } | ||
| 574 | |||
| 575 | T::regs().cfgr().modify(|reg| { | ||
| 576 | reg.set_jdiscen(false); // Will convert all channels for each trigger | ||
| 577 | }); | ||
| 578 | } | ||
| 579 | |||
| 580 | /// Configures the ADC to use a DMA ring buffer for continuous data acquisition. | 528 | /// Configures the ADC to use a DMA ring buffer for continuous data acquisition. |
| 581 | /// | 529 | /// |
| 582 | /// The `dma_buf` should be large enough to prevent DMA buffer overrun. | 530 | /// The `dma_buf` should be large enough to prevent DMA buffer overrun. |
| 583 | /// The length of the `dma_buf` should be a multiple of the ADC channel count. | 531 | /// The length of the `dma_buf` should be a multiple of the ADC channel count. |
| 584 | /// For example, if 3 channels are measured, its length can be 3 * 40 = 120 measurements. | 532 | /// For example, if 3 channels are measured, its length can be 3 * 40 = 120 measurements. |
| 585 | /// | 533 | /// |
| 586 | /// `read` method is used to read out measurements from the DMA ring buffer, and its buffer should be exactly half of the `dma_buf` length. | 534 | /// `read` method is used to read out measurements from the DMA ring buffer, and its buffer |
| 587 | /// It is critical to call `read` frequently to prevent DMA buffer overrun. | 535 | /// should be exactly half of the `dma_buf` length. It is critical to call `read` frequently to |
| 536 | /// prevent DMA buffer overrun. Or configure a software trigger for the regular ADC conversions | ||
| 537 | /// at a fixed interval. | ||
| 588 | /// | 538 | /// |
| 589 | /// [`read`]: #method.read | 539 | /// [`read`]: #method.read |
| 590 | pub fn into_ring_buffered<'a>( | 540 | pub fn into_ring_buffered<'a>( |
| @@ -654,6 +604,60 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 654 | RingBufferedAdc::new(dma, dma_buf) | 604 | RingBufferedAdc::new(dma, dma_buf) |
| 655 | } | 605 | } |
| 656 | 606 | ||
| 607 | /// Configure a sequence of injected channels | ||
| 608 | pub fn configure_injected_sequence<'a>( | ||
| 609 | &mut self, | ||
| 610 | sequence: impl ExactSizeIterator<Item = (&'a mut AnyAdcChannel<T>, SampleTime)>, | ||
| 611 | ) { | ||
| 612 | assert!(sequence.len() != 0, "Read sequence cannot be empty"); | ||
| 613 | assert!( | ||
| 614 | sequence.len() <= NR_INJECTED_RANKS, | ||
| 615 | "Read sequence cannot be more than 4 in length" | ||
| 616 | ); | ||
| 617 | |||
| 618 | // Ensure no conversions are ongoing and ADC is enabled. | ||
| 619 | Self::cancel_conversions(); | ||
| 620 | self.enable(); | ||
| 621 | |||
| 622 | // Set sequence length | ||
| 623 | T::regs().jsqr().modify(|w| { | ||
| 624 | w.set_jl(sequence.len() as u8 - 1); | ||
| 625 | }); | ||
| 626 | |||
| 627 | // Configure channels and ranks | ||
| 628 | for (n, (channel, sample_time)) in sequence.enumerate() { | ||
| 629 | Self::configure_channel(channel, sample_time); | ||
| 630 | |||
| 631 | match n { | ||
| 632 | 0..=3 => { | ||
| 633 | T::regs().jsqr().modify(|w| { | ||
| 634 | w.set_jsq(n, channel.channel()); | ||
| 635 | }); | ||
| 636 | } | ||
| 637 | 4..=8 => { | ||
| 638 | T::regs().jsqr().modify(|w| { | ||
| 639 | w.set_jsq(n - 4, channel.channel()); | ||
| 640 | }); | ||
| 641 | } | ||
| 642 | 9..=13 => { | ||
| 643 | T::regs().jsqr().modify(|w| { | ||
| 644 | w.set_jsq(n - 9, channel.channel()); | ||
| 645 | }); | ||
| 646 | } | ||
| 647 | 14..=15 => { | ||
| 648 | T::regs().jsqr().modify(|w| { | ||
| 649 | w.set_jsq(n - 14, channel.channel()); | ||
| 650 | }); | ||
| 651 | } | ||
| 652 | _ => unreachable!(), | ||
| 653 | } | ||
| 654 | } | ||
| 655 | |||
| 656 | T::regs().cfgr().modify(|reg| { | ||
| 657 | reg.set_jdiscen(false); // Will convert all channels for each trigger | ||
| 658 | }); | ||
| 659 | } | ||
| 660 | |||
| 657 | /// Start injected ADC conversion | 661 | /// Start injected ADC conversion |
| 658 | pub fn start_injected_conversion(&mut self) { | 662 | pub fn start_injected_conversion(&mut self) { |
| 659 | T::regs().cr().modify(|reg| { | 663 | T::regs().cr().modify(|reg| { |
