stm32f4xx/
adc.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5use crate::clocks::{phclk, Stm32f4Clocks};
6use core::cell::Cell;
7use kernel::hil;
8use kernel::platform::chip::ClockInterface;
9use kernel::utilities::cells::OptionalCell;
10use kernel::utilities::registers::interfaces::{ReadWriteable, Readable};
11use kernel::utilities::registers::{register_bitfields, ReadOnly, ReadWrite};
12use kernel::utilities::StaticRef;
13use kernel::ErrorCode;
14
15#[repr(C)]
16struct AdcRegisters {
17    sr: ReadWrite<u32, SR::Register>,
18    cr1: ReadWrite<u32, CR1::Register>,
19    cr2: ReadWrite<u32, CR2::Register>,
20    smpr1: ReadWrite<u32, SMPR1::Register>,
21    smpr2: ReadWrite<u32, SMPR2::Register>,
22    jofr1: ReadWrite<u32, JOFR::Register>,
23    jofr2: ReadWrite<u32, JOFR::Register>,
24    jofr3: ReadWrite<u32, JOFR::Register>,
25    jofr4: ReadWrite<u32, JOFR::Register>,
26    htr: ReadWrite<u32, HTR::Register>,
27    ltr: ReadWrite<u32, LTR::Register>,
28    sqr1: ReadWrite<u32, SQR1::Register>,
29    sqr2: ReadWrite<u32, SQR2::Register>,
30    sqr3: ReadWrite<u32, SQR3::Register>,
31    jsqr: ReadWrite<u32, JSQR::Register>,
32    jdr1: ReadOnly<u32, JDR::Register>,
33    jdr2: ReadOnly<u32, JDR::Register>,
34    jdr3: ReadOnly<u32, JDR::Register>,
35    jdr4: ReadOnly<u32, JDR::Register>,
36    dr: ReadOnly<u32, DR::Register>,
37}
38
39#[repr(C)]
40struct AdcCommonRegisters {
41    csr: ReadOnly<u32, CSR::Register>,
42    ccr: ReadWrite<u32, CCR::Register>,
43}
44
45register_bitfields![u32,
46    /// Status register
47    SR [
48        /// Overrun
49        OVR OFFSET(5) NUMBITS(1) [],
50        /// Regular channel start flag
51        STRT OFFSET(4) NUMBITS(1) [],
52        /// Injected channel start flag
53        JSTRT OFFSET(3) NUMBITS(1) [],
54        /// Injected channel end of conversion
55        JEOC OFFSET(2) NUMBITS(1) [],
56        /// Regular channel end of conversion
57        EOC OFFSET(1) NUMBITS(1) [],
58        /// Analog watchdog flag
59        AWD OFFSET(0) NUMBITS(1) []
60    ],
61    /// Control register 1
62    CR1 [
63        /// Overrun interrupt enable
64        OVRIE OFFSET(26) NUMBITS(1) [],
65        /// Resolution
66        RES OFFSET(24) NUMBITS(2) [],
67        /// Analog watchdog enable on regular channels
68        AWDEN OFFSET(23) NUMBITS(1) [],
69        /// Analog watchdog enable on injected channels
70        JAWDEN OFFSET(22) NUMBITS(1) [],
71        /// Discontinuous mode channel count
72        DISCNUM OFFSET(13) NUMBITS(3) [],
73        /// Discontinuous mode on injected channels
74        JDISCEN OFFSET(12) NUMBITS(1) [],
75        /// Discontinuous mode on regular channels
76        DISCEN OFFSET(11) NUMBITS(1) [],
77        /// Automatic injected group conversion
78        JAUTO OFFSET(10) NUMBITS(1) [],
79        /// Enable the watchdog on a single channel in scan mode
80        AWDSGL OFFSET(9) NUMBITS(1) [],
81        /// Scan mode
82        SCAN OFFSET(8) NUMBITS(1) [],
83        /// Interrupt enable for injected channels
84        JEOCIE OFFSET(7) NUMBITS(1) [],
85        /// Analog watchdog interrupt enable
86        AWDIE OFFSET(6) NUMBITS(1) [],
87        /// Interrupt enable for EOC
88        EOCIE OFFSET(5) NUMBITS(1) [],
89        /// Analog watchdog channel select bits
90        AWDCH OFFSET(0) NUMBITS(4) []
91    ],
92    /// Control register 2
93    CR2 [
94        /// Start conversion of regular channels
95        SWSTART OFFSET(30) NUMBITS(1) [],
96        /// External trigger enable for regular channels
97        EXTEN OFFSET(28) NUMBITS(2) [],
98        /// External event select for regular group
99        EXTSEL OFFSET(24) NUMBITS(4) [],
100        /// Start conversion of injected channels
101        JSWSTART OFFSET(22) NUMBITS(1) [],
102        /// External trigger enable for injected channels
103        JEXTEN OFFSET(20) NUMBITS(2) [],
104        /// External event select for injected group
105        JEXTSEL OFFSET(16) NUMBITS(4) [],
106        /// Data alignment
107        ALIGN OFFSET(11) NUMBITS(1) [],
108        /// End of conversion selection
109        EOCS OFFSET(10) NUMBITS(1) [],
110        /// DMA disable selection (for single ADC mode)
111        DDS OFFSET(9) NUMBITS(1) [],
112        /// Direct memory access mode (for single ADC mode)
113        DMA OFFSET(8) NUMBITS(1) [],
114        /// Continuous conversion
115        CONT OFFSET(1) NUMBITS(1) [],
116        /// A/D Converter ON / OFF
117        ADON OFFSET(0) NUMBITS(1) []
118    ],
119    /// Sample time register 1
120    SMPR1 [
121        /// Channel x sampling time selection
122        SMP18 OFFSET(24) NUMBITS(3) [],
123        SMP17 OFFSET(21) NUMBITS(3) [],
124        SMP16 OFFSET(18) NUMBITS(3) [],
125        SMP15 OFFSET(15) NUMBITS(3) [],
126        SMP14 OFFSET(12) NUMBITS(3) [],
127        SMP13 OFFSET(9) NUMBITS(3) [],
128        SMP12 OFFSET(6) NUMBITS(3) [],
129        SMP11 OFFSET(3) NUMBITS(3) [],
130        SMP10 OFFSET(0) NUMBITS(3) []
131    ],
132    /// Sample time register 2
133    SMPR2 [
134        /// Channel x sampling time selection
135        SMP9 OFFSET(27) NUMBITS(3) [],
136        SMP8 OFFSET(24) NUMBITS(3) [],
137        SMP7 OFFSET(21) NUMBITS(3) [],
138        SMP6 OFFSET(18) NUMBITS(3) [],
139        SMP5 OFFSET(15) NUMBITS(3) [],
140        SMP4 OFFSET(12) NUMBITS(3) [],
141        SMP3 OFFSET(9) NUMBITS(3) [],
142        SMP2 OFFSET(6) NUMBITS(3) [],
143        SMP1 OFFSET(3) NUMBITS(3) [],
144        SMP0 OFFSET(0) NUMBITS(3) []
145    ],
146    /// injected channel data offsetregister x
147    JOFR [
148        /// Data offsetfor injected channel x
149        JOFFSET OFFSET(0) NUMBITS(12) []
150    ],
151    /// Watchdog higher threshold register
152    HTR [
153        /// Analog watchdog higher threshold
154        HT OFFSET(0) NUMBITS(12) []
155    ],
156    /// Watchdog lower threshold register
157    LTR [
158        /// Analog watchdog lower threshold
159        LT OFFSET(0) NUMBITS(12) []
160    ],
161    /// Regular sequence register 1
162    SQR1 [
163        /// Regular channel sequence length
164        L OFFSET(20) NUMBITS(3) [],
165        /// 16th conversion in regular sequence
166        SQ16 OFFSET(15) NUMBITS(5) [],
167        /// 15th conversion in regular sequence
168        SQ15 OFFSET(10) NUMBITS(5) [],
169        /// 14th conversion in regular sequence
170        SQ14 OFFSET(5) NUMBITS(5) [],
171        /// 13th conversion in regular sequence
172        SQ13 OFFSET(0) NUMBITS(5) []
173    ],
174    /// Regular sequence register 2
175    SQR2 [
176        /// 12th conversion in regular sequence
177        SQ12 OFFSET(25) NUMBITS(5) [],
178        /// 11th conversion in regular sequence
179        SQ11 OFFSET(20) NUMBITS(5) [],
180        /// 10th conversion in regular sequence
181        SQ10 OFFSET(15) NUMBITS(5) [],
182        /// 9th conversion in regular sequence
183        SQ9 OFFSET(10) NUMBITS(5) [],
184        /// 8th conversion in regular sequence
185        SQ8 OFFSET(5) NUMBITS(5) [],
186        /// 7th conversion in regular sequence
187        SQ7 OFFSET(0) NUMBITS(5) []
188    ],
189    /// Regular sequence register 3
190    SQR3 [
191        /// 6th conversion in regular sequence
192        SQ6 OFFSET(25) NUMBITS(5) [],
193        /// 5th conversion in regular sequence
194        SQ5 OFFSET(20) NUMBITS(5) [],
195        /// 4th conversion in regular sequence
196        SQ4 OFFSET(15) NUMBITS(5) [],
197        /// 3rd conversion in regular sequence
198        SQ3 OFFSET(10) NUMBITS(5) [],
199        /// 2nd conversion in regular sequence
200        SQ2 OFFSET(5) NUMBITS(5) [],
201        /// 1st conversion in regular sequence
202        SQ1 OFFSET(0) NUMBITS(5) []
203    ],
204    /// Injected sequence register
205    JSQR [
206        /// Note:  When JL[1:0]=3 (4 injected conversions in the sequencer), the ADC converts the channels
207        ///      in the following order: JSQ1[4:0], JSQ2[4:0], JSQ3[4:0], and JSQ4[4:0].
208        ///      When JL=2 (3 injected conversions in the sequencer), the ADC converts the channels in the
209        ///      following order: JSQ2[4:0], JSQ3[4:0], and JSQ4[4:0].
210        ///      When JL=1 (2 injected conversions in the sequencer), the ADC converts the channels in
211        ///      starting from JSQ3[4:0], and then JSQ4[4:0].
212        ///      When JL=0 (1 injected conversion in the sequencer), the ADC converts only JSQ4[4:0]
213        ///      channel.
214        /// Injected sequence length
215        JL OFFSET(20) NUMBITS(2) [],
216        /// 4th conversion in injected sequence
217        JSQ4 OFFSET(15) NUMBITS(5) [],
218        /// 3rd conversion in injected sequence
219        JSQ3 OFFSET(15) NUMBITS(5) [],
220        /// 2nd conversion in injected sequence
221        JSQ2 OFFSET(15) NUMBITS(5) [],
222        /// 1st conversion in injected sequence
223        JSQ1 OFFSET(15) NUMBITS(5) []
224    ],
225    /// Injected data register x
226    JDR [
227        /// Injected data
228        JDATA OFFSET(0) NUMBITS(16) []
229    ],
230    /// Regular data register
231    DR [
232        /// Regular data
233        DATA OFFSET(0) NUMBITS(16) []
234    ],
235    /// Common status register
236    CSR [
237        /// Overrun flag of ADC1
238        OVR1 OFFSET(5) NUMBITS(1) [],
239        /// Regular channel Start flag of ADC1
240        STRT1 OFFSET(4) NUMBITS(1) [],
241        /// Injected channel Start flag of ADC1
242        JSTRT1 OFFSET(3) NUMBITS(1) [],
243        /// Injected channel end of conversion of ADC1
244        JEOC1 OFFSET(2) NUMBITS(1) [],
245        /// End of conversion of ADC1
246        EOC1 OFFSET(1) NUMBITS(1) [],
247        /// Analog watchdog flag of ADC1
248        AWD1 OFFSET(0) NUMBITS(1) []
249    ],
250    /// Common control register
251    CCR [
252        /// Temperature sensor and VREFINT enable
253        TSVREFE OFFSET(23) NUMBITS(1) [],
254        /// VBAT enable
255        VBATE OFFSET(22) NUMBITS(1) [],
256        /// ADC prescaler
257        ADCPRE OFFSET(16) NUMBITS(2) []
258    ]
259];
260
261const ADC1_BASE: StaticRef<AdcRegisters> =
262    unsafe { StaticRef::new(0x4001_2000 as *const AdcRegisters) };
263
264const ADC_COMMON_BASE: StaticRef<AdcCommonRegisters> =
265    unsafe { StaticRef::new(0x4001_2300 as *const AdcCommonRegisters) };
266
267#[allow(dead_code)]
268#[repr(u32)]
269#[derive(Copy, Clone, PartialEq)]
270pub enum Channel {
271    Channel0 = 0b00000,
272    Channel1 = 0b00001,
273    Channel2 = 0b00010,
274    Channel3 = 0b00011,
275    Channel4 = 0b00100,
276    Channel5 = 0b00101,
277    Channel6 = 0b00110,
278    Channel7 = 0b00111,
279    Channel8 = 0b01000,
280    Channel9 = 0b01001,
281    Channel10 = 0b01010,
282    Channel11 = 0b01011,
283    Channel12 = 0b01100,
284    Channel13 = 0b01101,
285    Channel14 = 0b01110,
286    Channel15 = 0b01111,
287    Channel16 = 0b10000,
288    Channel17 = 0b10001,
289    Channel18 = 0b10010,
290}
291
292#[allow(dead_code)]
293#[repr(u32)]
294enum DataResolution {
295    Bit12 = 0b00,
296    Bit10 = 0b01,
297    Bit8 = 0b10,
298    Bit6 = 0b11,
299}
300
301#[derive(Copy, Clone, PartialEq)]
302enum ADCStatus {
303    Idle,
304    Off,
305    OneSample,
306}
307
308pub struct Adc<'a> {
309    registers: StaticRef<AdcRegisters>,
310    common_registers: StaticRef<AdcCommonRegisters>,
311    clock: AdcClock<'a>,
312    status: Cell<ADCStatus>,
313    client: OptionalCell<&'a dyn hil::adc::Client>,
314}
315
316impl<'a> Adc<'a> {
317    pub const fn new(clocks: &'a dyn Stm32f4Clocks) -> Self {
318        Self {
319            registers: ADC1_BASE,
320            common_registers: ADC_COMMON_BASE,
321            clock: AdcClock(phclk::PeripheralClock::new(
322                phclk::PeripheralClockType::APB2(phclk::PCLK2::ADC1),
323                clocks,
324            )),
325            status: Cell::new(ADCStatus::Off),
326            client: OptionalCell::empty(),
327        }
328    }
329
330    pub fn enable(&self) {
331        // Enable adc clock
332        self.enable_clock();
333
334        // Enable ADC
335        self.registers.cr2.modify(CR2::ADON::SET);
336
337        // set idle state
338        self.status.set(ADCStatus::Idle);
339    }
340
341    pub fn handle_interrupt(&self) {
342        // Check if regular group conversion ended
343        if self.registers.sr.is_set(SR::EOC) {
344            // Clear interrupt
345            self.registers.cr1.modify(CR1::EOCIE::CLEAR);
346            if self.status.get() == ADCStatus::OneSample {
347                // set state
348                self.status.set(ADCStatus::Idle);
349            }
350            self.client
351                .map(|client| client.sample_ready((self.registers.dr.read(DR::DATA) as u16) << 4));
352        }
353    }
354
355    pub fn is_enabled_clock(&self) -> bool {
356        self.clock.is_enabled()
357    }
358
359    pub fn enable_clock(&self) {
360        self.clock.enable();
361    }
362
363    pub fn disable_clock(&self) {
364        self.clock.disable();
365    }
366
367    pub fn enable_temperature(&self) {
368        self.common_registers.ccr.modify(CCR::TSVREFE::SET);
369    }
370}
371
372struct AdcClock<'a>(phclk::PeripheralClock<'a>);
373
374impl ClockInterface for AdcClock<'_> {
375    fn is_enabled(&self) -> bool {
376        self.0.is_enabled()
377    }
378
379    fn enable(&self) {
380        self.0.enable();
381    }
382
383    fn disable(&self) {
384        self.0.disable();
385    }
386}
387
388impl<'a> hil::adc::Adc<'a> for Adc<'a> {
389    type Channel = Channel;
390
391    fn sample(&self, channel: &Self::Channel) -> Result<(), ErrorCode> {
392        if self.status.get() == ADCStatus::Off {
393            self.enable();
394        }
395        if *channel as u32 == 18 {
396            self.enable_temperature();
397        }
398        if self.status.get() == ADCStatus::Idle {
399            self.status.set(ADCStatus::OneSample);
400            self.registers.sqr1.modify(SQR1::L.val(0b0000));
401            self.registers.sqr3.modify(SQR3::SQ1.val(*channel as u32));
402            self.registers.cr1.modify(CR1::EOCIE::SET);
403            self.registers.cr2.modify(CR2::SWSTART::SET);
404            Ok(())
405        } else {
406            Err(ErrorCode::BUSY)
407        }
408    }
409
410    fn sample_continuous(
411        &self,
412        _channel: &Self::Channel,
413        _frequency: u32,
414    ) -> Result<(), ErrorCode> {
415        Err(ErrorCode::NOSUPPORT)
416    }
417
418    fn stop_sampling(&self) -> Result<(), ErrorCode> {
419        Err(ErrorCode::NOSUPPORT)
420    }
421
422    fn get_resolution_bits(&self) -> usize {
423        12
424    }
425
426    fn get_voltage_reference_mv(&self) -> Option<usize> {
427        Some(3300)
428    }
429
430    fn set_client(&self, client: &'a dyn hil::adc::Client) {
431        self.client.set(client);
432    }
433}
434
435/// Not yet supported
436impl<'a> hil::adc::AdcHighSpeed<'a> for Adc<'a> {
437    /// Capture buffered samples from the ADC continuously at a given
438    /// frequency, calling the client whenever a buffer fills up. The client is
439    /// then expected to either stop sampling or provide an additional buffer
440    /// to sample into. Note that due to hardware constraints the maximum
441    /// frequency range of the ADC is from 187 kHz to 23 Hz (although its
442    /// precision is limited at higher frequencies due to aliasing).
443    ///
444    /// - `channel`: the ADC channel to sample
445    /// - `frequency`: frequency to sample at
446    /// - `buffer1`: first buffer to fill with samples
447    /// - `length1`: number of samples to collect (up to buffer length)
448    /// - `buffer2`: second buffer to fill once the first is full
449    /// - `length2`: number of samples to collect (up to buffer length)
450    fn sample_highspeed(
451        &self,
452        _channel: &Self::Channel,
453        _frequency: u32,
454        buffer1: &'static mut [u16],
455        _length1: usize,
456        buffer2: &'static mut [u16],
457        _length2: usize,
458    ) -> Result<(), (ErrorCode, &'static mut [u16], &'static mut [u16])> {
459        Err((ErrorCode::NOSUPPORT, buffer1, buffer2))
460    }
461
462    /// Provide a new buffer to send on-going buffered continuous samples to.
463    /// This is expected to be called after the `samples_ready` callback.
464    ///
465    /// - `buf`: buffer to fill with samples
466    /// - `length`: number of samples to collect (up to buffer length)
467    fn provide_buffer(
468        &self,
469        buf: &'static mut [u16],
470        _length: usize,
471    ) -> Result<(), (ErrorCode, &'static mut [u16])> {
472        Err((ErrorCode::NOSUPPORT, buf))
473    }
474
475    /// Reclaim buffers after the ADC is stopped.
476    /// This is expected to be called after `stop_sampling`.
477    fn retrieve_buffers(
478        &self,
479    ) -> Result<(Option<&'static mut [u16]>, Option<&'static mut [u16]>), ErrorCode> {
480        Err(ErrorCode::NOSUPPORT)
481    }
482
483    fn set_highspeed_client(&self, _client: &'a dyn hil::adc::HighSpeedClient) {}
484}