1use crate::pm::{self, Clock, PBAClock};
13use core::cell::Cell;
14use kernel::hil;
15use kernel::utilities::registers::interfaces::{Readable, Writeable};
16use kernel::utilities::registers::{register_bitfields, ReadOnly, ReadWrite, WriteOnly};
17use kernel::utilities::StaticRef;
18use kernel::ErrorCode;
19
20#[repr(C)]
21pub struct DacRegisters {
22 cr: WriteOnly<u32, Control::Register>, mr: ReadWrite<u32, Mode::Register>, cdr: WriteOnly<u32, ConversionData::Register>, ier: WriteOnly<u32, InterruptEnable::Register>, idr: WriteOnly<u32, InterruptDisable::Register>, imr: ReadOnly<u32, InterruptMask::Register>, isr: ReadOnly<u32, InterruptStatus::Register>, _reserved0: [u32; 50], wpmr: ReadWrite<u32, WriteProtectMode::Register>, wpsr: ReadOnly<u32, WriteProtectStatus::Register>, _reserved1: [u32; 4], version: ReadOnly<u32, Version::Register>, }
36
37register_bitfields![u32,
38 Control [
39 SWRST 0
40 ],
41
42 Mode [
44 CLKDIV OFFSET(16) NUMBITS(16) [],
46 STARTUP OFFSET( 8) NUMBITS(8) [],
48 WORD OFFSET( 5) NUMBITS(1) [
50 HalfWordTransfer = 0b0,
51 FullWordTransfer = 0b1
52 ],
53 DACEN OFFSET( 4) NUMBITS(1) [],
55 TRGSEL OFFSET( 1) NUMBITS(3) [
57 ExternalTrigger = 0b000,
58 PeripheralTrigger = 0b001
59 ],
60 TRGEN OFFSET( 0) NUMBITS(1) [
62 InternalTrigger = 0b0,
63 ExternalTrigger = 0b1
64 ]
65 ],
66
67 ConversionData [
69 DATA OFFSET(0) NUMBITS(32) []
71 ],
72
73 InterruptEnable [
75 TXRDY 0
77 ],
78
79 InterruptDisable [
81 TXRDY 0
83 ],
84
85 InterruptMask [
87 TXRDY 0
89 ],
90
91 InterruptStatus [
93 TXRDY 0
95 ],
96
97 WriteProtectMode [
99 WPKEY OFFSET(8) NUMBITS(24) [],
101 WPEN OFFSET(0) NUMBITS(1) []
103 ],
104
105 WriteProtectStatus [
107 WPROTADDR OFFSET(8) NUMBITS(8) [],
109 WPROTERR OFFSET(0) NUMBITS(1) []
111 ],
112
113 Version [
115 VARIANT OFFSET(16) NUMBITS(3) [],
116 VERSION OFFSET( 0) NUMBITS(12) []
117 ]
118];
119
120const DAC_BASE: StaticRef<DacRegisters> =
122 unsafe { StaticRef::new(0x4003C000 as *const DacRegisters) };
123
124pub struct Dac {
125 registers: StaticRef<DacRegisters>,
126 enabled: Cell<bool>,
127}
128
129impl Dac {
130 pub const fn new() -> Self {
131 Self {
132 registers: DAC_BASE,
133 enabled: Cell::new(false),
134 }
135 }
136
137 fn initialize(&self) -> Result<(), ErrorCode> {
138 if !self.enabled.get() {
139 self.enabled.set(true);
140
141 pm::enable_clock(Clock::PBA(PBAClock::DACC));
143
144 self.registers.cr.write(Control::SWRST::SET);
146
147 let mr = Mode::WORD::HalfWordTransfer
154 + Mode::STARTUP.val(0xff)
155 + Mode::CLKDIV.val(0x60)
156 + Mode::TRGEN::InternalTrigger
157 + Mode::DACEN::SET;
158 self.registers.mr.write(mr);
159 }
160 Ok(())
161 }
162
163 pub fn handle_interrupt(&self) {}
165}
166
167impl hil::dac::DacChannel for Dac {
168 fn set_value(&self, value: usize) -> Result<(), ErrorCode> {
169 if !self.enabled.get() {
170 self.initialize()?;
171 }
172
173 if !self.registers.isr.is_set(InterruptStatus::TXRDY) {
175 return Err(ErrorCode::BUSY);
176 }
177
178 self.registers
180 .cdr
181 .write(ConversionData::DATA.val(value as u32));
182 Ok(())
183 }
184}