1use 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 SR [
48 OVR OFFSET(5) NUMBITS(1) [],
50 STRT OFFSET(4) NUMBITS(1) [],
52 JSTRT OFFSET(3) NUMBITS(1) [],
54 JEOC OFFSET(2) NUMBITS(1) [],
56 EOC OFFSET(1) NUMBITS(1) [],
58 AWD OFFSET(0) NUMBITS(1) []
60 ],
61 CR1 [
63 OVRIE OFFSET(26) NUMBITS(1) [],
65 RES OFFSET(24) NUMBITS(2) [],
67 AWDEN OFFSET(23) NUMBITS(1) [],
69 JAWDEN OFFSET(22) NUMBITS(1) [],
71 DISCNUM OFFSET(13) NUMBITS(3) [],
73 JDISCEN OFFSET(12) NUMBITS(1) [],
75 DISCEN OFFSET(11) NUMBITS(1) [],
77 JAUTO OFFSET(10) NUMBITS(1) [],
79 AWDSGL OFFSET(9) NUMBITS(1) [],
81 SCAN OFFSET(8) NUMBITS(1) [],
83 JEOCIE OFFSET(7) NUMBITS(1) [],
85 AWDIE OFFSET(6) NUMBITS(1) [],
87 EOCIE OFFSET(5) NUMBITS(1) [],
89 AWDCH OFFSET(0) NUMBITS(4) []
91 ],
92 CR2 [
94 SWSTART OFFSET(30) NUMBITS(1) [],
96 EXTEN OFFSET(28) NUMBITS(2) [],
98 EXTSEL OFFSET(24) NUMBITS(4) [],
100 JSWSTART OFFSET(22) NUMBITS(1) [],
102 JEXTEN OFFSET(20) NUMBITS(2) [],
104 JEXTSEL OFFSET(16) NUMBITS(4) [],
106 ALIGN OFFSET(11) NUMBITS(1) [],
108 EOCS OFFSET(10) NUMBITS(1) [],
110 DDS OFFSET(9) NUMBITS(1) [],
112 DMA OFFSET(8) NUMBITS(1) [],
114 CONT OFFSET(1) NUMBITS(1) [],
116 ADON OFFSET(0) NUMBITS(1) []
118 ],
119 SMPR1 [
121 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 SMPR2 [
134 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 JOFR [
148 JOFFSET OFFSET(0) NUMBITS(12) []
150 ],
151 HTR [
153 HT OFFSET(0) NUMBITS(12) []
155 ],
156 LTR [
158 LT OFFSET(0) NUMBITS(12) []
160 ],
161 SQR1 [
163 L OFFSET(20) NUMBITS(3) [],
165 SQ16 OFFSET(15) NUMBITS(5) [],
167 SQ15 OFFSET(10) NUMBITS(5) [],
169 SQ14 OFFSET(5) NUMBITS(5) [],
171 SQ13 OFFSET(0) NUMBITS(5) []
173 ],
174 SQR2 [
176 SQ12 OFFSET(25) NUMBITS(5) [],
178 SQ11 OFFSET(20) NUMBITS(5) [],
180 SQ10 OFFSET(15) NUMBITS(5) [],
182 SQ9 OFFSET(10) NUMBITS(5) [],
184 SQ8 OFFSET(5) NUMBITS(5) [],
186 SQ7 OFFSET(0) NUMBITS(5) []
188 ],
189 SQR3 [
191 SQ6 OFFSET(25) NUMBITS(5) [],
193 SQ5 OFFSET(20) NUMBITS(5) [],
195 SQ4 OFFSET(15) NUMBITS(5) [],
197 SQ3 OFFSET(10) NUMBITS(5) [],
199 SQ2 OFFSET(5) NUMBITS(5) [],
201 SQ1 OFFSET(0) NUMBITS(5) []
203 ],
204 JSQR [
206 JL OFFSET(20) NUMBITS(2) [],
216 JSQ4 OFFSET(15) NUMBITS(5) [],
218 JSQ3 OFFSET(15) NUMBITS(5) [],
220 JSQ2 OFFSET(15) NUMBITS(5) [],
222 JSQ1 OFFSET(15) NUMBITS(5) []
224 ],
225 JDR [
227 JDATA OFFSET(0) NUMBITS(16) []
229 ],
230 DR [
232 DATA OFFSET(0) NUMBITS(16) []
234 ],
235 CSR [
237 OVR1 OFFSET(5) NUMBITS(1) [],
239 STRT1 OFFSET(4) NUMBITS(1) [],
241 JSTRT1 OFFSET(3) NUMBITS(1) [],
243 JEOC1 OFFSET(2) NUMBITS(1) [],
245 EOC1 OFFSET(1) NUMBITS(1) [],
247 AWD1 OFFSET(0) NUMBITS(1) []
249 ],
250 CCR [
252 TSVREFE OFFSET(23) NUMBITS(1) [],
254 VBATE OFFSET(22) NUMBITS(1) [],
256 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 self.enable_clock();
333
334 self.registers.cr2.modify(CR2::ADON::SET);
336
337 self.status.set(ADCStatus::Idle);
339 }
340
341 pub fn handle_interrupt(&self) {
342 if self.registers.sr.is_set(SR::EOC) {
344 self.registers.cr1.modify(CR1::EOCIE::CLEAR);
346 if self.status.get() == ADCStatus::OneSample {
347 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
435impl<'a> hil::adc::AdcHighSpeed<'a> for Adc<'a> {
437 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 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 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}