msp432/ref_module.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
5//! Reference Module (REF)
6
7use core::cell::Cell;
8use kernel::utilities::registers::interfaces::{ReadWriteable, Readable};
9use kernel::utilities::registers::{register_bitfields, register_structs, ReadWrite};
10use kernel::utilities::StaticRef;
11
12register_structs! {
13 /// REF
14 RefRegisters {
15 /// REF Control Register 0
16 (0x000 => ctl0: ReadWrite<u16, CTL0::Register>),
17 (0x002 => @END),
18 }
19}
20register_bitfields![u16,
21 CTL0 [
22 /// Reference enable
23 REFON OFFSET(0) NUMBITS(1) [
24 /// Disables reference if no other reference requests are pending
25 DisablesReferenceIfNoOtherReferenceRequestsArePending = 0,
26 /// Enables reference in static mode
27 EnablesReferenceInStaticMode = 1
28 ],
29 /// Reference output buffer
30 REFOUT OFFSET(1) NUMBITS(1) [
31 /// Reference output not available externally
32 ReferenceOutputNotAvailableExternally = 0,
33 /// Reference output available externally. If ADC14REFBURST = 0, output is available
34 REFOUT_1 = 1
35 ],
36 /// Temperature sensor disabled
37 REFTCOFF OFFSET(3) NUMBITS(1) [
38 /// Temperature sensor enabled
39 TemperatureSensorEnabled = 0,
40 /// Temperature sensor disabled to save power
41 TemperatureSensorDisabledToSavePower = 1
42 ],
43 /// Reference voltage level select
44 REFVSEL OFFSET(4) NUMBITS(2) [
45 /// 1.2 V available when reference requested or REFON = 1
46 _12VAvailableWhenReferenceRequestedOrREFON1 = 0,
47 /// 1.45 V available when reference requested or REFON = 1
48 _145VAvailableWhenReferenceRequestedOrREFON1 = 1,
49 /// 2.5 V available when reference requested or REFON = 1
50 _25VAvailableWhenReferenceRequestedOrREFON1 = 3
51 ],
52 /// Reference generator one-time trigger
53 REFGENOT OFFSET(6) NUMBITS(1) [
54 /// No trigger
55 NoTrigger = 0,
56 /// Generation of the reference voltage is started by writing 1 or by a hardware tri
57 GenerationOfTheReferenceVoltageIsStartedByWriting1OrByAHardwareTrigger = 1
58 ],
59 /// Bandgap and bandgap buffer one-time trigger
60 REFBGOT OFFSET(7) NUMBITS(1) [
61 /// No trigger
62 NoTrigger = 0,
63 /// Generation of the bandgap voltage is started by writing 1 or by a hardware trigg
64 GenerationOfTheBandgapVoltageIsStartedByWriting1OrByAHardwareTrigger = 1
65 ],
66 /// Reference generator active
67 REFGENACT OFFSET(8) NUMBITS(1) [
68 /// Reference generator not active
69 ReferenceGeneratorNotActive = 0,
70 /// Reference generator active
71 ReferenceGeneratorActive = 1
72 ],
73 /// Reference bandgap active
74 REFBGACT OFFSET(9) NUMBITS(1) [
75 /// Reference bandgap buffer not active
76 ReferenceBandgapBufferNotActive = 0,
77 /// Reference bandgap buffer active
78 ReferenceBandgapBufferActive = 1
79 ],
80 /// Reference generator busy
81 REFGENBUSY OFFSET(10) NUMBITS(1) [
82 /// Reference generator not busy
83 ReferenceGeneratorNotBusy = 0,
84 /// Reference generator busy
85 ReferenceGeneratorBusy = 1
86 ],
87 /// Bandgap mode
88 BGMODE OFFSET(11) NUMBITS(1) [
89 /// Static mode
90 StaticMode = 0,
91 /// Sampled mode
92 SampledMode = 1
93 ],
94 /// Variable reference voltage ready status
95 REFGENRDY OFFSET(12) NUMBITS(1) [
96 /// Reference voltage output is not ready to be used
97 ReferenceVoltageOutputIsNotReadyToBeUsed = 0,
98 /// Reference voltage output is ready to be used
99 ReferenceVoltageOutputIsReadyToBeUsed = 1
100 ],
101 /// Buffered bandgap voltage ready status
102 REFBGRDY OFFSET(13) NUMBITS(1) [
103 /// Buffered bandgap voltage is not ready to be used
104 BufferedBandgapVoltageIsNotReadyToBeUsed = 0,
105 /// Buffered bandgap voltage is ready to be used
106 BufferedBandgapVoltageIsReadyToBeUsed = 1
107 ]
108 ]
109];
110
111const REF_BASE: StaticRef<RefRegisters> =
112 unsafe { StaticRef::new(0x4000_3000 as *const RefRegisters) };
113
114pub struct Ref {
115 registers: StaticRef<RefRegisters>,
116 ref_voltage: Cell<ReferenceVoltage>,
117}
118
119#[repr(u16)]
120#[derive(Copy, Clone, PartialEq)]
121pub enum ReferenceVoltage {
122 Volt1_2 = 0,
123 Volt1_45 = 1,
124 Volt2_5 = 3,
125}
126
127pub trait AnalogReference {
128 /// Return the configured reference voltage in mV
129 fn ref_voltage_mv(&self) -> usize;
130}
131
132impl Ref {
133 pub const fn new() -> Ref {
134 Ref {
135 registers: REF_BASE,
136 ref_voltage: Cell::new(ReferenceVoltage::Volt1_2),
137 }
138 }
139
140 /// Set the reference voltage of this module which will be used in the ADC and DAC modules.
141 /// The default voltage is 1.2V.
142 pub fn select_ref_voltage(&self, ref_voltage: ReferenceVoltage) {
143 self.ref_voltage.set(ref_voltage);
144 while self.registers.ctl0.is_set(CTL0::REFGENBUSY) {}
145 self.registers
146 .ctl0
147 .modify(CTL0::REFVSEL.val(ref_voltage as u16));
148 }
149
150 /// Enable or disable the internal temperature sensor.
151 /// The default-setting is enabled.
152 pub fn enable_temp_sensor(&self, enable: bool) {
153 while self.registers.ctl0.is_set(CTL0::REFGENBUSY) {}
154 // Enable the temperature sensor
155 // Enable the reference module, otherwise the temperature sensor doesn't work
156 self.registers
157 .ctl0
158 .modify(CTL0::REFTCOFF.val((!enable) as u16) + CTL0::REFON::SET);
159 }
160}
161
162impl AnalogReference for Ref {
163 fn ref_voltage_mv(&self) -> usize {
164 match self.ref_voltage.get() {
165 ReferenceVoltage::Volt1_2 => 1200,
166 ReferenceVoltage::Volt1_45 => 1450,
167 ReferenceVoltage::Volt2_5 => 2500,
168 }
169 }
170}