1use crate::pm::{self, Clock, PBAClock};
13use core::cell::Cell;
14use kernel::ErrorCode;
15use kernel::hil;
16use kernel::utilities::StaticRef;
17use kernel::utilities::registers::interfaces::{Readable, Writeable};
18use kernel::utilities::registers::{
19 ReadOnly, ReadWrite, WriteOnly, register_bitfields, register_structs,
20};
21
22register_structs! {
23 pub DacRegisters {
24 (0x000 => cr: WriteOnly<u32, Control::Register>),
25 (0x004 => mr: ReadWrite<u32, Mode::Register>),
26 (0x008 => cdr: WriteOnly<u32, ConversionData::Register>),
27 (0x00C => ier: WriteOnly<u32, InterruptEnable::Register>),
28 (0x010 => idr: WriteOnly<u32, InterruptDisable::Register>),
29 (0x014 => imr: ReadOnly<u32, InterruptMask::Register>),
30 (0x018 => isr: ReadOnly<u32, InterruptStatus::Register>),
31 (0x01C => _reserved0: [u32; 50]),
32 (0x0E4 => wpmr: ReadWrite<u32, WriteProtectMode::Register>),
33 (0x0E8 => wpsr: ReadOnly<u32, WriteProtectStatus::Register>),
34 (0x0EC => _reserved1: [u32; 4]),
35 (0x0FC => version: ReadOnly<u32, Version::Register>),
36 (0x100 => @END),
37 }
38}
39
40register_bitfields![u32,
41 Control [
42 SWRST 0
43 ],
44
45 Mode [
47 CLKDIV OFFSET(16) NUMBITS(16) [],
49 STARTUP OFFSET( 8) NUMBITS(8) [],
51 WORD OFFSET( 5) NUMBITS(1) [
53 HalfWordTransfer = 0b0,
54 FullWordTransfer = 0b1
55 ],
56 DACEN OFFSET( 4) NUMBITS(1) [],
58 TRGSEL OFFSET( 1) NUMBITS(3) [
60 ExternalTrigger = 0b000,
61 PeripheralTrigger = 0b001
62 ],
63 TRGEN OFFSET( 0) NUMBITS(1) [
65 InternalTrigger = 0b0,
66 ExternalTrigger = 0b1
67 ]
68 ],
69
70 ConversionData [
72 DATA OFFSET(0) NUMBITS(32) []
74 ],
75
76 InterruptEnable [
78 TXRDY 0
80 ],
81
82 InterruptDisable [
84 TXRDY 0
86 ],
87
88 InterruptMask [
90 TXRDY 0
92 ],
93
94 InterruptStatus [
96 TXRDY 0
98 ],
99
100 WriteProtectMode [
102 WPKEY OFFSET(8) NUMBITS(24) [],
104 WPEN OFFSET(0) NUMBITS(1) []
106 ],
107
108 WriteProtectStatus [
110 WPROTADDR OFFSET(8) NUMBITS(8) [],
112 WPROTERR OFFSET(0) NUMBITS(1) []
114 ],
115
116 Version [
118 VARIANT OFFSET(16) NUMBITS(3) [],
119 VERSION OFFSET( 0) NUMBITS(12) []
120 ]
121];
122
123const DAC_BASE: StaticRef<DacRegisters> =
125 unsafe { StaticRef::new(0x4003C000 as *const DacRegisters) };
126
127pub struct Dac {
128 registers: StaticRef<DacRegisters>,
129 enabled: Cell<bool>,
130}
131
132impl Dac {
133 pub const fn new() -> Self {
134 Self {
135 registers: DAC_BASE,
136 enabled: Cell::new(false),
137 }
138 }
139
140 fn initialize(&self) -> Result<(), ErrorCode> {
141 if !self.enabled.get() {
142 self.enabled.set(true);
143
144 pm::enable_clock(Clock::PBA(PBAClock::DACC));
146
147 self.registers.cr.write(Control::SWRST::SET);
149
150 let mr = Mode::WORD::HalfWordTransfer
157 + Mode::STARTUP.val(0xff)
158 + Mode::CLKDIV.val(0x60)
159 + Mode::TRGEN::InternalTrigger
160 + Mode::DACEN::SET;
161 self.registers.mr.write(mr);
162 }
163 Ok(())
164 }
165
166 pub fn handle_interrupt(&self) {}
168}
169
170impl hil::dac::DacChannel for Dac {
171 fn set_value(&self, value: usize) -> Result<(), ErrorCode> {
172 if !self.enabled.get() {
173 self.initialize()?;
174 }
175
176 if !self.registers.isr.is_set(InterruptStatus::TXRDY) {
178 return Err(ErrorCode::BUSY);
179 }
180
181 self.registers
183 .cdr
184 .write(ConversionData::DATA.val(value as u32));
185 Ok(())
186 }
187}